0

I have a Component that I attach to projectiles spawned by my character. I would like to make a callback function that is called when the projectile hits a valid target.

In Component.h I declare a function :

    template<class T>
    void OnTargetHit( void (T::*Callback)() );

In Component.cpp is implementation:

template<class T>
void UInterpolationComponent::OnTargetHit( void (T::*Callback)() )
{
    (T::*Callback)();
}

Now in my Character.cpp I would like to Get the component and assign it a "callback" function, a function that would be triggered when te target is hit, ofcourse this component could be applied to different Actors, therefore I want to pass a function from the calling class so I provide a specific implementation:

    AActor* Projectile = GetWorld()->SpawnActor<AActor>(PrimaryAttackProjectile_BP, GetActorLocation(), Rotation);

    UInterpolationComponent* InterpComp = Cast<UInterpolationComponent>(Projectile->GetComponentByClass(UInterpolationComponent::StaticClass()));
    InterpComp->InterpSpeed = 1800.f;
    InterpComp->bHoming = false;
    InterpComp->StaticTarget = Location;
    InterpComp->bIsDestroyable = true;
    InterpComp->OnTargetHit<ACartagraCharacter>(&CalculateDamage);

The problem is with the last line of code :

    InterpComp->OnTargetHit<ACartagraCharacter>(&CalculateDamage);

I'm not sure if I should pass an ampersand or not, If I should Include the class name, I tried all of the following:

    InterpComp->OnTargetHit<ACartagraCharacter>(CalculateDamage);
    InterpComp->OnTargetHit<ACartagraCharacter>(&ACartagraCharacter::CalculateDamage);

None of them work, either gives me an ampersand error, or if in the last case presented it gives me a linker error. I also tried making them static functions, but that doesn't make too much sense as the component is instanced on each spawned projectile. I'm new to template functions and not sure how I'm supposed to do this. Please help.

  • 2
    "*In Component.h I declare a function ... In Component.cpp is implementation*" - that won't work for a template function, see [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/) – Remy Lebeau Mar 12 '21 at 18:02
  • 1
    When using a pointer-to-member, you also need an object to access the member from, via the `.*` or `->*` operator, eg: `template void OnTargetHit( T *obj, void (T::*Callback)() );` ... `(obj->*Callback)();` and then you can call it like: `InterpComp->OnTargetHit(&SomeCartagraCharacterObj, &ACartagraCharacter::CalculateDamage);` – Remy Lebeau Mar 12 '21 at 18:04
  • 1
    IMO the best (and easiest way) to do it, is using `std::function` "event slots" in combination with lambda callback functions. Capturing `this` might be tricky though (regarding object's lifetime), but that's the case anyways as @Remy pointed out. – πάντα ῥεῖ Mar 12 '21 at 18:09
  • Thank you guys for fast and accurate response so much!! EDIT: Thanks REMY!!! Thank you so much. Finally understand templates now. I love you! – Filip Matjašec Mar 13 '21 at 09:35

0 Answers0