Create and Use Delegates in Unreal Engine 5 Using C++
Just like Event Dispatchers, delegates are a great way to communicate with different actors and classes throughout the program.
Software Versions: Unreal Engine 5.4.4 | Rider 2024.2.7
Project Name: MyProject
Similar to event dispatchers, Unreal C++ delegates are used to communicate with other classes, actors, and, objects in the world.
This example branches off the previous post about BP event dispatchers, so rather than health, I updated the W_Health_Mana
User Widget
with a mana progress bar.
Next, in this example I created a component that can be added to any actor to react or bind to the delegate event.
In an attempt to keep things simple, this component is extremely light and only declares a delegate. Delegates can absolutely be used in a variety of ways, another great delegate example is Epic's First Person Shooter Template PickUp Class. The .cpp
file will be empty this example.
MyDelegateComponent.h
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MyDelegateComponent.generated.h"
UDELEGATE(BlueprintCallable)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUpdateManaCPP, float, ManaValue);
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class MYPROJECT_API UMyDelegateComponent : public UActorComponent
{
GENERATED_BODY()
public:
/** Delegate to whom anyone can subscribe to receive this event */
UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "Mana")
FUpdateManaCPP UpdateManaCPP;
};
Above UCLASS
we declare one delegate signature called FUpdateManaCPP
that accepts one float parameter called ManaValue
. Then in the class we declare UpdateManaCPP
that can be used throughout the code base.
We can now add this component to any actor. In this example I copied over the Third Person template character Blueprint and added the component to the BP along with the widget.
With the component added we can now call it from another actor. Next, we can create a simple actor that when the character overlaps it we can broadcast the event with value that will update the character's total Mana
.
MyDelegateActorTrigger.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDelegateActorTrigger.generated.h"
class UBoxComponent;
class UTextRenderComponent;
UCLASS()
class MYPROJECT_API AMyDelegateActorTrigger : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyDelegateActorTrigger();
UPROPERTY(EditAnywhere)
USceneComponent* DefaultSceneRoot;
UPROPERTY(EditAnywhere)
UStaticMeshComponent* MyMesh;
UPROPERTY(EditAnywhere)
UBoxComponent* MyBox;
UPROPERTY(EditAnywhere)
UTextRenderComponent* MyText;
UPROPERTY(EditAnywhere)
float ManaValue = -10.0f;
UFUNCTION()
void OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};
MyDelegateActorTrigger.cpp
#include "MyDelegateActorTrigger.h"
#include "MyDelegateComponent.h"
#include "Components/BoxComponent.h"
#include "Components/TextRenderComponent.h"
// Sets default values
AMyDelegateActorTrigger::AMyDelegateActorTrigger()
{
DefaultSceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
DefaultSceneRoot->bVisualizeComponent = true;
RootComponent = DefaultSceneRoot;
MyMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MyMesh"));
MyMesh->SetupAttachment(RootComponent);
MyText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("MyText"));
MyText->SetupAttachment(RootComponent);
MyBox = CreateDefaultSubobject<UBoxComponent>(TEXT("MyBox"));
MyBox->OnComponentBeginOverlap.AddDynamic(this, &AMyDelegateActorTrigger::OnBeginOverlap);
MyBox->SetupAttachment(RootComponent);
}
void AMyDelegateActorTrigger::OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor && OtherActor != this)
{
UMyDelegateComponent* MyDelComp = OtherActor->FindComponentByClass<UMyDelegateComponent>();
if (MyDelComp != nullptr)
{
MyDelComp->UpdateManaCPP.Broadcast(ManaValue);
}
}
}
The MyDelegateActorTrigger
is a basic actor that has a few components to build it up, but most importantly it has box collision component that on overlap broadcasts to the character's MyDelegateComponent
's UpdateManaCPP
function and passes along the ManaValue
to the event.
Everything can be done in a variety of ways, for simplicity I decided to just quickly update the character's mana value inside the UserWidget
. Not the best for long term practice, but I wanted to just quickly bind to an C++ delegate and have the UI react.
With everything in place we can start building the level. I created two Blueprints inheriting from MyDelegateActorTrigger
, I only had to update the mesh, change the material, and set the material. I set the first trigger to have a mana value of -10.0f
to decrease the player's mana while the second platform has a value of 10.0f
to increase the player's mana.
Below is the final result.
I hope this helps. I'm looking forward to using delegate more in the future.
Harrison McGuire