TakeDamage on Destructible Actor

I’m trying to detect when a class inherited from ADestructibleActor has been destroyed. I couldn’t find any clues on how to implement the OnActorFracture or OnComponentFracture events in C++ so I decided to hack it by overriding TakeDamage(). Unfortunately, nothing I’ve tried has called my override function. I know it’s doing something because the projectile registers a hit and the mesh fractures.

This code is based on the First Person C++ template and I’ve left the projectile class alone except for modifying OnHit().

Anyone know how to override TakeDamage() for a destructible actor or how to get the OnActorFracture or OnComponentFracture events in my class?

In MyActor’s header file:

float TakeDamage(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser) override;

Side note, I’ve tried every combination of the UFUNCTION(), override, virtual keywords I could think of.

In MyActor’s source file:

float AMyActor::TakeDamage(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser)
{
    float returnVal = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);

    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, "Damage");
    }

    // More stuff

    return returnVal;
}

In my projectile’s OnHit function:

AMyActor* pTarget(Cast<AMyActor>(OtherActor));
if (pTarget)
{
    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, "Hit");
    }
    pTarget->GetDestructibleComponent()->ApplyDamage(100.0f, pTarget->GetActorLocation(), NormalImpulse, 0.0f);
}

This call completely ignores the engine’s TakeDamage functionality.

pTarget->GetDestructibleComponent()->ApplyDamage(100.0f, pTarget->GetActorLocation(), NormalImpulse, 0.0f);

Because it apply damage directly to APEX destructible, so overriding TakeDamage gives you nothing.

If you want to bind OnActorFracture in your declare function based on this signature:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FActorFractureSignature, const FVector &, HitPoint, const FVector &, HitDirection);

Something like this:

UFUNCTION()
void OnMyActorFracture(const FVector& HitPoint, const FVector& HitDirection);

Then bind it in constructor:

OnActorFracture.AddUniqueDynamic(this, &MyDestructibleActor::OnMyActorFracture);

Then try hit with projectile this destructible and wait for the delegate call.

Thank you, that worked.

For anyone else who reads this, I was also able to add OnComponentFracture by tracing it back to where it was declared in DestructibleComponent.h and then looking for the delegate declaration that used FComponentFractureSignature. Creating my own function with the same parameter list and then adding it in the constructor with GetDestructibleComponent()->OnComponentFracture.AddDynamic(this, &AMyActor::OnComponentFracture); got it to work.

Now I’m running into some oddness with respawning the Actor. Once the Actor is fractured, I send an alert to the GameMode so it will call Destroy() on that Actor instance after a certain amount of time. A half-second after destroying the mesh (to make sure there’s no collision), I spawn a new Actor in that location. If the new Actor has the same name as the destroyed Actor, I’ll get a weird incomplete spawn (see attached). But if the new Actor has a different name, it’ll work correctly. Is there something else besides just calling Destroy() that needs to be done? As far as I can tell from the World Outliner, the original Actor is gone well before the second one attempts to spawn.

48976-weirdspawn.png

My Actor is a Blueprinted class and the spawn code is based on: How to spawn a simple cube in C++? - Programming & Scripting - Epic Developer Community Forums. I just modified the SpawnBP() call to include a name.

Y’know, next time I start hitting my head against a wall, I’m just going to walk away for a couple hours.

Apparently, Destroy() doesn’t really completely destroy an Actor (don’t know if that’s a bug or working as intended). Similar to here: I cant fully destroy actors after I spawn them! ActorIterator still finds them. What is Better Destroy Method? - Programming & Scripting - Epic Developer Community Forums, I found that calling MyActorPtr->K2_DestroyActor(); followed by GetWorld()->ForceGarbageCollection(true); will actually get rid of my Actor so I can correctly spawn another one with the same name.