Unreal C++ Delegates in Blueprints: Make an Event Dispatcher in C++

Table of Contents

Works in Unreal Engine 4.27 and 5.0 to 5.8. Updated October 2026.

Quick answer: only dynamic delegates are visible to Blueprints. Declare a dynamic multicast delegate and mark the property BlueprintAssignable:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);

UPROPERTY(BlueprintAssignable, Category = "Health")
FOnHealthChanged OnHealthChanged;

Call OnHealthChanged.Broadcast(Health); in C++, and Blueprints can bind to it like any Event Dispatcher.

Choosing the correct delegate type

Anytime you want your C++ code to work with Blueprints, it has to support reflection. Unreal has four kinds of delegates, and only one of them supports reflection:

Delegate typeMacroVisible to Blueprints?
Single-castDECLARE_DELEGATENo
MulticastDECLARE_MULTICAST_DELEGATENo
EventDECLARE_EVENTNo
Dynamic (single or multicast)DECLARE_DYNAMIC_DELEGATE / DECLARE_DYNAMIC_MULTICAST_DELEGATEYes

Use dynamic multicast for an Event Dispatcher that many listeners can bind to. Use dynamic single-cast when a Blueprint passes a callback into one of your functions (see the end of this page).

Step 1: Declare the delegate and the property

Put the macro after the .generated.h include and before UCLASS. In dynamic delegates, every parameter needs a type and a name.

				
					#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "HealthComponent.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChanged, float, NewHealth, float, Delta);

UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MYGAME_API UHealthComponent : public UActorComponent
{
	GENERATED_BODY()

protected:
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health")
	float Health = 100.0f;

public:
	/** Fires whenever Health changes. Blueprints bind to it like an Event Dispatcher. */
	UPROPERTY(BlueprintAssignable, Category = "Health")
	FOnHealthChanged OnHealthChanged;

	UFUNCTION(BlueprintCallable, Category = "Health")
	virtual void ApplyDamage(float Damage);
};
				
			

Step 2: Broadcast it from C++

				
					void UHealthComponent::ApplyDamage(float Damage)
{
	Health -= Damage;

	OnHealthChanged.Broadcast(Health, -Damage);
}
				
			

Broadcasting with nothing bound is safe. It simply does nothing.

Step 3: Bind to it in Blueprints

  1. Add the component to an actor and select it in the Components panel.
  2. In the Details panel, scroll to Events and click the + next to On Health Changed. Unreal creates a bound event in the graph.
  3. Or, in the graph, drag from a reference to the component and add Bind Event to On Health Changed, then connect a custom event with matching inputs.

To let Blueprints call the dispatcher too, add BlueprintCallable: UPROPERTY(BlueprintAssignable, BlueprintCallable).

Binding from C++

Use AddDynamic with a function marked UFUNCTION():

				
					HealthComponent->OnHealthChanged.AddDynamic(this, &AMyHUDActor::HandleHealthChanged);
				
			

If the handler isn’t a UFUNCTION(), the binding silently does nothing. See why your AddDynamic delegate is not working.

Passing a Blueprint callback into a function

For “call me back when this finishes”, use a dynamic single-cast delegate as a parameter. Blueprints then get a red delegate pin they can connect a custom event to.

				
					DECLARE_DYNAMIC_DELEGATE_OneParam(FOnLoadFinished, bool, bSucceeded);

UFUNCTION(BlueprintCallable, Category = "Loading")
virtual void LoadProfile(FOnLoadFinished OnLoadFinished);
				
			

Inside, call OnLoadFinished.ExecuteIfBound(true); when the work is done.

Common problems

ProblemFix
Delegate doesn’t appear in BlueprintsUse a DYNAMIC macro and mark the property BlueprintAssignable.
Compile error on the delegate macroMove it after the .generated.h include, and give every parameter a name.
Parameter type not allowedUse Blueprint types (float, int32, FString, UObject*, USTRUCTs), not raw C++ types like std::string.
Bound event never firesBind in BeginPlay, not the constructor, and check something calls Broadcast.

FAQ

What’s the difference between BlueprintAssignable and BlueprintCallable?

BlueprintAssignable lets Blueprints bind to the delegate. BlueprintCallable lets Blueprints broadcast it.

Are dynamic delegates slower?

Slightly, because they go through reflection. For events like health changes you won’t notice. Keep non-dynamic delegates for very hot C++-only paths.

Related tutorials