C++ Event dispatchers: How do we implement them?

Can we create event dispatchers in C++ and then expose them to blueprints which inherit from the C++ class?

If so, what would be the appropriate reflection macro to use for it?

1 Like

Yes you can, with delegates.

1 Like

Hey there,

it happens that i did this 2 days ago. Since i want code examples in the docs, i will give you a small code example on how to setup a delegate
to be used in Blueprints and C++.

First you need to add your Delegate through the macro in your classes header file:



DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestDelegate);


“FTestDelegate” represents the Typename of your upcomming delegates.
You can use Params by adding _OneParam or _TwoParams and so on at the end.


DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FTestDelegate, PARAMTYPE, PARAMNAME);

Example:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FTestDelegate, float, Damage);


You place this outside of your class declaration(example):



#pragma once

#include "GameFramework/PlayerController.h"
#include "MyPlayerController.generated.h"

/**
 * 
 */

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestDelegate);

UCLASS()
class SOCKETTEST_API AMyPlayerController : public APlayerController
{
	GENERATED_UCLASS_BODY()
	
	
public:
	virtual void Tick(float DeltaTime) override;
	virtual void BeginPlay() override;

        void TestFunction();

	UPROPERTY(BlueprintAssignable, Category = "Test")
		FTestDelegate OnTestDelegate;
};


Now you should have spotted the UPROPERTY at the bottom of my example.
This is the part you add a Delegate (here called “OnTestDelegate”).
The UPROPERTY “BlueprintAssignable” give you the possibility to bind/assign
this function to a custom event in your BP Child class.

You should be able to bind a delegate in C++ AND Blueprint and call both
bound functions/events through c++.



UPROPERTY(BlueprintAssignable, Category = "Test")
	FTestDelegate OnTestDelegate;


If you want to add a function to it, you need to call “AddDynamic” on the delegate.
The editor won’t show you this and maybe shows an error. Just try to compile anyway


Here is an example for the normal, non param delegate from above, inside your CPP File:



OnTestDelegate.AddDynamic(this, &AMyPlayerController::TestFunction);


If you now want to call your delegate inside your code do this at the desired position:


OnTestDelegate.Broadcast();

I hope this helps (:

27 Likes

Hello,

New to UE4 c++ API.

How do I subscribe to OnTestDelegate from a different c++ actor.

Thank you,
.

2 Likes

Why did you use


DECLARE_DYNAMIC_MULTICAST_DELEGATE

over


DECLARE_EVENT

?

DECLARE_DYNAMIC_MULTICAST_DELEGATE is very often used in the gameplay framework so I am wondering why I would use it instead of DECLARE_EVENT.

Hello,

This is what worked



#include "Acpp_character.h" // to get the class declaration

void Acpp_tennisBall::BeginPlay ()
{
    Acpp_character *c =  Cast <Acpp_character>(GetWorld ()->GetFirstPlayerController ()->GetCharacter ());
    c->OnMoveToPosition.AddDynamic (this, &Acpp_tennisBall::MoveToPosition);
}


Is there a elegant way to do this via ConstructorHelpers. The Acpp_character object is instantiated only ingame through the custom GameMode’s Default Pawn Class.

Do I need to remove delegates (REmoveDynamic) when the actor is destroyed? How does that work with UE garbage collection management?

It is actually dynamic delegates. If you mark BlueprintAssignable it will appears as blueprints’ eventdispatcher

I’m having trouble binding methods from other objects. Can someone help me?

The subscription to a delegate is a weak reference, so you don’t have to worry about them keeping objects from being garbage collected.

1 Like

Can someone show how is it done? Bind a Delegate of one Actor to another? I’m trying but the game keeps crashing. Can anyone supply a functional example code? Please?

Something like this:



void AMyActor::MyFunction(AActor* AnotherActor)
{
   // When AnotherActor is destroyed, call this->HandleAnotherActorDestroyed()
   AnotherActor->OnDestroyed.AddDynamic(this, &AMyActor::MyHandle);
}

void AMyActor::HandleAnotherActorDestroyed()
{
   // Do something here
}


It’s been a while since I did this, but both from my experience using the delegates and looking at their usage in the code base the big difference between DECLARE_EVENT and DECLARE_DYNAMIC_MULTICAST_DELEGATE is that dynamic delegates can be looked up by name and therefore can be used/exposed to blueprints. I don’t think I’ve ever been able to use DECLARE_EVENT from a blueprint.

I tried something like this and it is crashing during gameplay. how to you define the delegate?

OnTestDelegate.Broadcast();

How could i do this in blueprint?

Hi !
I not sure if this is the right place to ask this question, so please guide me if it is not.

Current I am doing the “Time Attack Racer” example, I wrote the ‘checkpoint’ entirely in C++ while the other actors in blueprint (Cause I need the checkpoint to do other things for my project).But I am Stuck at the Event dispatcher, I tried the above ’ event dispatch’ method in my checkpoint and cannot bind it to ‘Tracker’ in the blueprint.
Any Help is appreciated !
Thank :wink:

cheer

Hi, fairly new UE user here.
I noticed making the delegate function private also works. Is there any reason for it to be public instead of private?

Thanks!

If it works with them being private, then no.
Have you tested binding the Delegate in a different BP Class then “MyPlayerController”?
Blueprint exposed UPROPERTY’s always tell me they can’t be private. So I thought protected and public is better here :x

You can add “meta = (AllowPrivateAccess = true)” to the UPROPERTY macro on a private field, which explicitly gives Blueprint permission to read and write that field. For dynamic multicast delegates I prefer to keep the field private, apply AllowPrivateAccess, and provide a public read-only accessor to the delegate for C++ code to bind to it. That way users of your code can’t accidentally overwrite the delegate with a different instance.

3 Likes

Very useful post here. Having just implemented a C+±declared Event Dispatcher per the above - a note, for full functionality you will want to add BlueprintCallable as well to allow your blueprint to call your event dispatcher:

> UPROPERTY(BlueprintAssignable, BlueprintCallable, Category = “Test”)
> FTestDelegate OnTestDelegate;

4 Likes