Why use an event dispatcher over calling a function?

I mean is there any benefit of using an event dispatcher from another blueprint? (not level bp). A target reference is needed in both cases, and after getting said reference you might as well just call the function in question.

Lets say I have an instant death function. Whenever the player steps on a red colored object (lets say i have 3 bp’s, a cube, a cylinder and a pyramid) the player dies. So what would be the difference in this theoretical scenario between every object getting a ref to the game mode (let’s say this is the bp where the player death function is set up) and calling PlayerDeath over doing the same thing but assigning a PlayerDeath custom event to a dispatcher, and calling that?

I think this might be a bit confusing, but here’s my question in a more straightforward way:

Event Dispatchers can only take events without inputs. Functions can have both inputs and outputs (so can regular events.). Why would I call an assigned event dispatcher from another blueprint that isn’t the level bp, over just firing the custom event/functiion? I need a target reference in both cases, so it seems that Event Dispatchers are inferior and even pointless. What am I missing? I’ve read the documentation and watched a few videos on the topic, and these are mostly used for bp to level bp communication.

From my current understanding, the only upside an event dispatcher could have would be if it was static, and required no getting/casting of the object that holds it. But I don’t see a setting in the details panel.

Maybe I just have the wrong expectations, I was under the impression that the event dispatchers were identical to the static events in Unity/Mono, and it was their static nature and easy access that appealed to me.

one source - all object execute

like pause, if you need some sort of pause in game, you can bind it and make different logic in every object, then you would bind it to pause button, you still need a reference, “but backward one”, everyone should know where the button is, but button doesn’t care about where everyone else, button would execute one function, without any reference and whole level would stop.

Function A can be called by objects A B C D E etc. Same thing, one source - all execute. Could you perhaps give me an example of what you’re talking about. If I understand correctly, button references self, whereas every other object references button, because that’s where the dispatcher is. But the same procedure is followed for function/custom ev calling.

but source does not need to know all targets, only targets need to know, which means you can dynamically spawn and destroy targets and retain control over them.

Do you want a centralized or a decentralized architecture? Do you want to maintain a list of everything that needs to be updated when you update the main object, or would you rather just put out an event that the main object updated and let any object that cares to subscribe to the event do so? Here’s an example: Let’s say you keep a count of remaining enemies in the game state. You then want to show that count in a UMG widget. You could certainly just bind the text field in the widget directly to the game state, but that’s going to update every single render tick and since this count doesn’t really update that often, that sure seems like overkill. It would be better to just know when the count changes. Getting a reference to the UMG widget which may or may not exist from the game state is not a workable solution… rather, just raise a RemainingEnemiesCount event with the enemies count in the game state whenever it changes and then bind to that event in the UMG widget. Even better, now any object in the game that would like to react to that count changing can just subscribe to that event and you don’t have to change a thing on your game state. You now have a decentralized architecture that is very scalable and performant.

Now, you are actually right about one thing. The dispatcher system actually just keeps a list of delegates to call when you raise the event, and is reaching out and calling the functions on each subscribed object, which is the exact same thing as you doing it manually by getting a reference to an object and calling the function. You could build this yourself and maintain that list yourself, but why do that when it is built right into the system? Sometimes a direct reference does make sense, but if you have any sort of complex interaction that requires updating information among multiple objects or logically disparate objects, definitely consider using events. You’ll thank yourself as things get more complicated down the road.

2 Likes

It is kind of simple, when one actor needs communicate to many actors - use event dispatchers
When you need get actors of multiple classes into list (and then call their function) - use blueprint interface (it has a bit more usefull functionality than that)
When you want to communicate to multiple objects with same clas - get all actors of class, cast to and call function in loop (but interfaces are more elegant and flexible here)
When you need one to one communication, just cast to and call function
So there is way (tool) for about every possible need we may have.

for eg to communicate between player pawn and player controller i always use cast to and call function (singleplayer game has only one player pawn)
when i want to make my own “event tick” that fires every .25sec (every frame is unecessary spamming for a lot of tasks, and i am tired of comparing time to when it was last executed in every single event tick of every single class), for this i use dispatcher, it is perfect for that role.

Ps. Also I prefer to use function and call it with parameter over updating/reading variables in another blueprint, functions let me keep track of what is updated from outside.

2 Likes

Ok, maybe I’m just stupid. I get the idea of having an event that is subscribed to by others, and can be called at any time. But here’s what’s perplexing me.

29a87b3b09.png
So this is how an event that has logic in it is assigned, it’s pretty straightforward, so no problems there on my end.


And this is how I call an event when something happens right? So I still do need a reference to the target, in this case the ExampleGameMode since it holds the dispatcher.

But here’s what’s perplexing me.


This doesn’t require any binding, follows the same structure (get,cast) and holds the benefit of available input.

Or I could outright call the custom event without doing any assignment.

If the event dispatcher was static and required no reference, I would definitely see the point of it. But as it currently is, it just seems pointless since it doesn’t do anything better than just calling stuff. I mean, I always thought that a static event saves performance since, well, no need to get stuff, and is therefore faster. Am I just using this wrong? I’ve read your replies and I understand the concept, my point is that to me it looks like calling a dispatcher, a custom event or a function is pretty much the same thing. I could have 1000 enemies calling something when destroyed, and that something could either be a function or a dispatcher, and in both cases it would have the same performance impact, no?

P.S: Btw there is a setting in the class defaults about the Event Tick interval, and it takes a float, so need for functions :stuck_out_tongue: Although I must admit, I saw it after I’d already set up a once per second tick :smiley:

You’re not entirely wrong. They are very similar and I doubt there is a ton of performance difference. Oh, except you are wrong about the inputs. You can pass parameters in an event just fine. Click on the event dispatcher in the variable list and you’ll see that you can define inputs the same way you would do for a function. The real purpose is really inversion of control. You can have 1000 enemies calling something when destroyed, or you can have one thing calling 1000 enemies. Events make that second part easier to manage and keeps it loosely coupled. There’s no such thing as a globally static function or event, it’s static on something… in Unity everything inherits from a GameObject/MonoBehavior and that’s what the event is on… in UE4 everything doesn’t inherit from the same thing, so there’s a bit more flexibility but it means you have to put that event on something and reference that something. There’s no right answer here, it’s all about design and maintainability.

Oh it just friggin hit me…yeah I get it I’ve just been using it wrong, I’d need to create an event dispatcher on the enemy, and then if I have 5 different enemies I can call the dispatcher from the game mode and all of them will execute different logic. Also, thanks for the input thingy, I didn’t notice it cuz I thought that the inputs are defined in the Bind node.

As a side note, I was under the impression that everything in UE4 inherits from Object, seeing how it’s above Actor, I figured a static would be defined there. But anyway that’s not a big deal I just wanted to understand what the point was of dispatchers, and now I have it cleared up. Thanks guys,

Kensei what? The only way you would be able to do what your saying on 5 different enimies is if they all had their own event bound to the dispatcher and they also would need casting from the game mode from actor to that enemy unless they are all children classes of a parent enemy class and in that case you could still pass it directly to the function. So I’m not sure how this clarified anything. I’m still just as confused as when I started reading.

If I wanted to do what your saying above I would simply use an interface on my enemy. I would do an interface call and if my enemy implemented that interface then it would execute the event. I wouldn’t need to cast to anything in this case and I could have unique logic for each enemy.

Honestly I think the only thing that binding an event to a dispatcher would ever do is reduce the need to loop through a class to get each instance of them to call an event or function. So maybe “this” example is the only reason I could think of that it may benefit me.

Event Dispatchers lets Object A listen to when Object B does something. Object B doesn’t need to know that Object A even exists it just calls a Event Dispatcher on itself. This is also known as a part of the Observer pattern.

There is a key difference. Object A wants something to happen to 5 enemies in response to an event.

With interfaces, Object A needs a reference to each of the 5 enemies. The enemies do not need a reference to Object A.

With dispatchers, each enemy needs a reference to Object A, but Object A doesn’t need a reference to any of the enemies.

So the two designs are “opposite” in that way. They both have their uses, depending on the situation.

Components should generally not be dependent on a specific Actor so how do the Component alert the Actor that and Event has occurred? You can’t implement an interface on a component, but you can use Event Dispatchers. Binding to a component event dispatcher on an Actor is as easy as pressing the green + on the Event. The Actor is dependent on its component no-matter what so you won’t “gain” any decoupling from using an interface even if you could.

Exactly!!! This is the reason I use Get all actors of class, so easy and fast. The only issue I am having is on the console it freezes a moment when these are used when loading

There is a vehicle that needs to talk to an actor BP and I was using Get all actors of class, get copy, because there is only one and then change a variable. Now I may have to have to Vehicle store the variable in the Game Instance and then have the Actor BP check the game instance for the variable state. Seems like a pain but if it works.

I though that the Dispatchers and interfaces you could just broadcast out your event but it seems like to have to have a reference to each actor.

Here’s the answer in a simple way:

The only benefit of event dispatchers over casting is game architecture modularity.

  1. Memory load: As you build and scale a game, if you cast to things from a base class (usually Character), that class will grow in size and bloat. This means your entire game will be referenced at all times. This means insane loading times and bad performance.

  2. Quality of life: Always casting also means your quality of life decreases. For one, you won’t have to navigate through a monster Character class every time you want to change/add something. But more importantly, if you use event dispatchers, you can put all the functionality for an object on that object itself. This is a huge workflow improvement because you don’t have to navigate to a base class, open it up, and put the other side of the functionality in there every time you want to communicate between objects. Just work in one blueprint when you’re designing it. If you don’t use event dispatchers (and interfaces), down the road you’ll find yourself with 15 blueprints open at all times trying to remember where stuff is and what you were even doing in the first place.

In summary: They do not make the code any smaller/shorter/simpler. They only make it more modular. They only structure it differently. This is key. And this helps both you and the computer not suffer with large complex projects.

2 Likes