Download

How to get onhit events to fire with collisions?

I’ve been stuck on this problem for the last 2 days and I can’t seem to find any useful documentation.
All I want is for the onhit() function to fire when an object is hit.

In constructor of .cpp file


Bullet = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Bullet"));

static ConstructorHelpers::FObjectFinder<UStaticMesh> MyBullet(TEXT("/Game/StarterContent/Shapes/Shape_Sphere"));

Bullet->SetStaticMesh(MyBullet.Object);

Bullet->BodyInstance.SetCollisionProfileName("Projectile");

Bullet->SetSimulatePhysics(true);

Bullet->OnComponentHit.AddDynamic(this, &ABullet::OnHit);

void ABullet::OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{

	Destroy();
	if (OtherActor && (OtherActor != this) && OtherComp)
	{
		OtherComp->DestroyComponent(false);

	}

I’ve tried looking at samples, tutorials, it just never seems to work

Make sure both actors have simulation generated hit events enabled.

Thank you so much Pumpy you’ve really helped me out :).
Here’s the code for setting up the generate hit events within a class in case anyone wondered.

Bullet->SetNotifyRigidBodyCollision(true);

I’m not sure if you got this fixed or not but for me it is a little misleading. I prefer that any mesh, sound, collision components to be set in the BP without any requirements for the C++ side of things. After all that’s the beauty of the integration between C++ and BP. And I’ve run into this exact problem.

Have you tried:

For the bullet:



.h
    UFUNCTION()
    void OnHit(AActor* SelfActor, AActor* OtherActor, FVector NormalImpulse, const FHitResult& Hit);

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Movement)
    UProjectileMovementComponent* ProjectileMovement;


.cpp
AMyBullet::AMyBullet(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
    ProjectileMovement = ObjectInitializer.CreateDefaultSubobject<UProjectileMovementComponent>(this, TEXT("Movement"));
    ProjectileMovement->UpdatedComponent = RootComponent;

    OnActorHit.AddDynamic(this, &AMyBullet::OnHit);

    InitialLifeSpan = 30.0f;
    PrimaryActorTick.bCanEverTick = true;
}


void AMyBullet::SetInitVelocity(const FVector& ShootDirection)
{
    if (ProjectileMovement)
    {
        ProjectileMovement->Velocity = ShootDirection * ProjectileMovement->InitialSpeed;
    }
}


void AMyBullet::OnHit(AActor* SelfActor, AActor* OtherActor, FVector NormalImpulse, const FHitResult& Hit)
{
    FColor DisplayColor = FColor::Yellow;
    const FString DebugMessage(OtherActor->GetName());
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, DisplayColor, DebugMessage);

    if (OtherActor)
    {
        if (OtherActor->IsA(APawn::StaticClass()))
        {
            APawn* Pawn(Cast<APawn>(OtherActor));
            if (Pawn)
            {
                float DamageAmount = 600.0f;
                const FDamageEvent DamageEvent;
                AController* EventInstigator = nullptr;
                AActor* DamageCauser = this;

                Pawn->TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
            }
        }
    }

    Destroy();
}


For an actor/pawn:



.h
    UFUNCTION()
    void OnHit(AActor* SelfActor, AActor* OtherActor, FVector NormalImpulse, const FHitResult& Hit);

.cpp
AMyPawn::AMyPawn(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
    PrimaryActorTick.bCanEverTick = true;
    OnActorHit.AddDynamic(this, &AMyPawn::OnHit);
}


void AMyPawn::OnHit(AActor* SelfActor, AActor* OtherActor, FVector NormalImpulse, const FHitResult& Hit)
{
    FColor DisplayColor = FColor::Yellow;
    const FString DebugMessage(OtherActor->GetName());
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, DisplayColor, DebugMessage);

    if (OtherActor)
    {
        if (OtherActor->IsA(ABullet::StaticClass()))
            Destroy();
    }
}


This is still very much a work-in-progress that I am sharing incase it helps in some way.

The little OnActorHit.AddDynamic() was found here:
https://answers.unrealengine.com/questions/171631/onhit-not-working-correctly-c.html

And a really nice projectile walkthrough is here:

Btw, while running the game press ~, then enter “show collision” to see the collision boxes.

Another update:

Instead of relying on C++ code to know anything about collisions, other than responding to the OnHit event, I was able to set the collision component on my static mesh projectile with the following:



Collision Complexity:     DEFAULT
Customized Collision:    CHECKED


And in the Blueprint Class that includes the static mesh I have the following:



Simulate Physics:        UNCHECKED

Collision
Simulation Generates Hit Events:    CHECKED
Collision Presets:                           PAWN
Use CCD:                                      CHECKED


Now my projectiles and (mechanical) skeletal meshes collide properly.

Btw, the ProjectileMovement component has a Projectile Gravity Scale, which defaults to 1, giving your projectiles the parabolic trajectory.