Download

Projectile collides with Character when shooting upwards!

My Projectile collides with the Character that fired it when shooting upwards.

This is how I spawn it in the Weapon class:

MyOwner is the Character that owns the Weapon


    FVector SocketLocation = MyOwner->GetMesh()->GetSocketLocation((FName("WeaponSocket")));
    FVector SocketRotation = MyOwner->GetMesh()->GetSocketRotation((FName("WeaponSocket"))).Vector();

    FVector CameraLoc;
    FRotator CameraRot;

    MyOwner->GetActorEyesViewPoint(CameraLoc, CameraRot);

    FVector Origin = SocketLocation;
    FVector ShootDir = CameraRot.Vector();

    // trace from camera to check what's under crosshair
    const float ProjectileAdjustRange = Range;
    const FVector StartTrace = GetCameraDamageStartLocation(ShootDir);
    const FVector EndTrace = StartTrace + (ShootDir * ProjectileAdjustRange);

    FHitResult Impact = WeaponTrace(StartTrace, EndTrace);

    // and adjust directions to hit that actor
    if (Impact.bBlockingHit)
    {
        const FVector AdjustedDir = (Impact.ImpactPoint - Origin).GetSafeNormal();
        bool bWeaponPenetration = false;

        const float DirectionDot = FVector::DotProduct(AdjustedDir, ShootDir);
        if (DirectionDot < 0.0f)
        {
            // shooting backwards = weapon is penetrating
            bWeaponPenetration = true;
        }

        else if (DirectionDot < 0.5f)
        {
            // check for weapon penetration if angle difference is big enough
            // raycast along weapon mesh to check if there's blocking hit
            FVector MuzzleStartTrace = Origin - SocketRotation * 150.0f;
            FVector MuzzleEndTrace = Origin;
            FHitResult MuzzleImpact = WeaponTrace(MuzzleStartTrace, MuzzleEndTrace);

            if (MuzzleImpact.bBlockingHit)
            {
                bWeaponPenetration = true;
            }
        }

        if (bWeaponPenetration)
        {
            // spawn at crosshair position
            Origin = Impact.ImpactPoint - ShootDir * 10.0f;
        }
        else
        {
            // adjust direction to hit
            ShootDir = AdjustedDir;
        }
    }

    FTransform SpawnTM(MyOwner->GetMesh()->GetSocketLocation((FName("WeaponSocket"))));

    APAProjectile* Projectile = Cast<APAProjectile>(UGameplayStatics::BeginDeferredActorSpawnFromClass(this, ProjectileClass, SpawnTM));

    if (Projectile)
    {
        Projectile->Instigator = Instigator;
        Projectile->SetOwner(this);
        Projectile->InitVelocity(ShootDir);        // here we set the direction of our projectile

        UGameplayStatics::FinishSpawningActor(Projectile, SpawnTM);
    }


The **WeaponSocket **is in the Skeleton and I’ve set it in a position where the weapon would be:

But when I shoot upwards, the Projectile detects the collision and applies damage to the “shooter”.

How could I solve?

Thanks in advance.

bump if there’s a better way to achieve projectile shooting, let me know

Hey there,

Try calling IgnoreActorWhenMoving(this, true) on the projectile’s collision component, ‘this’ being your character.



MyProjectileCollision->IgnoreActorWhenMoving(MyCharacter, /*bShouldIgnore=*/true);


Do this before calling UGameplayStatics::FinishSpawningActor()

Hi and thanks for the answer.

After adding that line of code, this is what happens:

As you can see, when the Character (on the left) shoots upwards, the Projectile goes behind the Character himself and not towards the sky.

Why do you start with a trace? To shoot a projectile you only need transform and direction. Remove all the trace code and just spawn the projectile.

I use the trace to get the direction! Don’t know how to do it otherwise!

Whats wrong with this direction?


FVector ShootDir = CameraRot.Vector();

What should be wrong?

Nothing, that’s my point. I should be clearer; remove all code that calculates the direction, including the trace. Keep only the snippet above.
Test it! What happens?

Thank you! It solves the problem, BUT…

rara.jpg

The projectile hits the wall BEFORE it aligns with the crosshair.

This means the projectile doesn’t hit the wall in the point I was aiming.

I’m quite sure that in every FPS the projectile hits the point you were aiming with the crosshair. This is a problem I don’t know how to solve!

If you are using physical projectiles they will drop if you have a reasonable speed, but that’s expected. The player need to lead the target and also compensate for how much the projectile will drop for the distance. For our game we always fire the projectile aligned with the crosshair, not really 100% correct but it feels better and is consistant between weapon types.

The projectile in this case is a rocket, so it doesn’t drop: it goes forward until it hits something. Any hint?

Look into your Projectile Movemement Component and find Gravity, you should be able to change the scale.

It doesn’t have gravity. The problem is what I described before: it takes time ti align with the crosshair (since the projectile is spawned in the weapon socket location)

So you have an RPG that you fire from the hip and want it to hit exactly where the crosshair points to, ok slighty different from what I was thinking about. Can you change it to be a shoulder mounted RPG instead and then fire from the camera? Otherwise you are back to something similar that you started with.

Of course: the rocket has to hit the point I’m aiming at!

That’s the way it works in 99,9% of videogames I believe.

But something tells me I shouldn’t spawn the projectile at the weapon muzzle.

Any suggestions?

I don’t see why spawning your projectile at the muzzle would be a bad idea, how else would you do it? I do recommend pooling your projectiles in an object pool instead of spawning them if you have a lot.

The alternative would be to spawn the projectile in front of the camera, so it will SURELY hit the crosshair.

Spawning it from the weapon muzzle causes the issue I described some posts ago

How about, when shooting the weapon

  1. FVector TargetLocation = Do a line trace or get hit result under mouse cursor or whatever determines the target location where your weapon is pointing at
  2. FVector StartLocation = Get the weapons missile launch location (a Slot location, for example)
  3. Use

UKismetMathLibrary::FindLookAtRotation(StartLocation, TargetLocation);

to get the rotation needed to get from the start point to the end point in a straight line.
That should give you the proper direction/rotation to shoot from your weapons missile spawn location to wherever you want to shoot at, no matter where your missile launch location is…

If you want to get the direction as a FVector instead of a Rotator, use


UKismetMathLibrary::FindLookAtRotation(StartLocation, TargetLocation).Vector();

If the compiler can’t find UKismetMathLibrary, do


#include "Kismet/KismetMathLibrary.h"

Intellisense might complain (it does for me) that FindLookAtRotation is private/inaccessible, but it should still compile and work just fine.

Thank you for the detailed explanation!

The problem isn’t the implementation, but the system itself!

Should projectiles start from the muzzle weapon or from the camera?