Hello, I am following Tom Looman’s Unreal C++ Course.
I have an Attribute Component with a MultiCast Delegate ‘FOnHealthChanged’, and an ASTargetDummy Actor class, which has an AttributeComponent. ASTargetDummy has a function OnHealthChanged that is bound to AttributeComponent’s FOnHealthChanged delegate, and triggers correct when Broadcast. However, I also have a TargetDummyBP that inherits from ASTargetDummy, and when I try to use the OnHealthChanged event of it’s AttributeComponent, it does not trigger.
I have closed the Editor and Rebuilt/Recompiled multiple times. Does anyone know what the problem may be? I will include the source code of the Attribute Component, Target Dummy class, and Target Dummy BP.
STargetDummy.h
class USAttributeComponent;
UCLASS()
class ACTIONROGUELIKE_API ASTargetDummy : public AActor
{
GENERATED_BODY()
public:
ASTargetDummy();
protected:
UPROPERTY(VisibleAnywhere)
USAttributeComponent* AttributeComponent;
UPROPERTY(VisibleAnywhere)
class UStaticMeshComponent* StaticMeshComponent;
virtual void PostInitializeComponents() override;
UFUNCTION()
void OnHealthChanged(AActor* InstigatorActor, USAttributeComponent* OwningComponent, float NewHealth, float OldHealth, float Delta);
};
STargetDummy.cpp
// Sets default values
ASTargetDummy::ASTargetDummy()
{
StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>("StaticMesh");
RootComponent = StaticMeshComponent;
AttributeComponent = CreateDefaultSubobject<USAttributeComponent>("AttributeComponent");
}
void ASTargetDummy::PostInitializeComponents()
{
Super::PostInitializeComponents();
AttributeComponent->OnHealthChanged.AddDynamic(this, &ASTargetDummy::OnHealthChanged);
}
void ASTargetDummy::OnHealthChanged(AActor* InstigatorActor, USAttributeComponent* OwningComponent, float NewHealth, float OldHealth, float Delta)
{
if (Delta < 0.0f)
{
StaticMeshComponent->SetScalarParameterValueOnMaterials("TimeToHit", GetWorld()->GetTimeSeconds());
}
}
SAttributeComponent.h
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FOnHealthChanged, AActor*, InstigatorActor, USAttributeComponent*, OwningComponent, float, NewHealth, float, OldHealth, float, Delta);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ACTIONROGUELIKE_API USAttributeComponent : public UActorComponent
{
GENERATED_BODY()
public:
USAttributeComponent();
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Attributes")
float Health = 100.0f;
public:
UFUNCTION(BlueprintCallable)
bool IsAlive() const;
UPROPERTY(BlueprintAssignable, Transient)
FOnHealthChanged OnHealthChanged;
UFUNCTION(BlueprintCallable, Category = "Attributes")
bool ApplyHealthDelta(float delta);
};
SAttributeComponent.cpp
USAttributeComponent::USAttributeComponent()
{
Health = 100.0f;
}
bool USAttributeComponent::IsAlive() const
{
return Health > 0.0f;
}
bool USAttributeComponent::ApplyHealthDelta(float delta)
{
const float OldHealth = Health;
Health = FMath::Clamp(Health + delta, 0.0f, /*MaxHealth*/ 100.0f);
OnHealthChanged.Broadcast(nullptr, this, Health, OldHealth, delta);
return true;
}
TargetDummyBP
Any help is appreciated, thank you.