So, as far as I know, binding to an event dispatcher requires a hard reference to the blueprint that calls it, while interfaces do not.
Why would you use event dispatchers? Are there any benefits against interfaces?
They are not the same use case, at-all.
Dispatcher talks to many actors in one call. Problem is, you have to bind using a known type.
Interface is way of sending and receiving messages with actors without knowing anything about them.
As above, they serve different purposes. Also:
This actor will spawn 2 new actors, bind them and then destroy itself:
Even though itâs gone, and so are the hards refs, the connection between those two dynamically spawned actors remains intact. You canât do that with an Interface.
If you bind 100000 delegates, a single call would be incredibly performant. Were you to send 100000 interface calls instead, you would not be able to, most likely⌠not in the next 5s while everything has to come to stop. Interface calls are slowish, but the required loop iteration would be sluggish AF.
This makes it sound like I should use event dispatchers whenever possible, even when passing values from one BP to another, and only use interfaces when I have no choice.
Am I right on this?
If the goal could be achieved with either, what would you choose?
Instant crash vs Instantaneous. You must have tried running a long BP loop, surely? Test it yourself, takes a minute to set it up - or do have a look at what interface does under the hood.
Interfaces every time [âŚ] But hey, both options have their fans and detractors. Thatâs how its always been
This makes no sense whatsoever. You use all methods of comms made available to you, quite often combine them altogether.
This makes it sound like I should use event dispatchers whenever possible
Interface comms and EDs serve different purposes. You choose a tool for the job, you do not design a job around a set of tools. If youâre making an item inspection systems where you juggle unrelated classes, you will use an interface. If half the classes need to delegate something, you would add that, too.
You always needed a target for every interface call. ED is registered once, thatâs it. And event binding can be removed run-time, too.
You mean if I have multiple copies of the same actor containing an interface call, in the level, it gets called every time as opposed to EDs?
Just to add a bit about the use of dispatchers: Observer pattern - Wikipedia
Weâre comparing apples to oranges. Theyâre not comparable. Itâs not that it gets called, for the interface to deliver a message, you must explicitly send it to every instance every time you want something done.
In most situations, you will have little choice but to use one over the other because thatâs the job at hand.
I also do not agree with EDs being messy, on the contrary. As soon as you add multiple interfaces, you will immediately see the clutter since every call is now available for every class even though they do not implement it.
⢠use an interface when you do not know the class youâre dealing with. The player walks around and Kicks
stuff. We do not know what theyâre going to kick. A rock? A door? A bucket? Air? A chicken? We want those entities to react but I donât want to build a crazy deep inheritance chain since Air has nothing in commmon with a Chicken. This is a great job for an interface.
⢠I know precisely what happens when Chickens get the boot - so I can set it up ahead of time and then never worry about it again. When kicked, any chicken will broadcast a distress call to the 12 city guards. Thatâs a job for an Event Dispatcher.
The best part is that chickens and guards do not need to know about each otherâs existence.
The player kicks a chicken via an interface â chicken dispatches a distress call to everyone who was told to listen.
two options I use
-
make your own event dispatcher using interfaces, ie you have an array of listening objects and send an event by interface to them.
-
use an event component where youâll have a hard ref to the component but since thats all it does itâll be a super small footprint
-
(i wish) allow interfaces to return event delegates? is this not possible?
All 12 guards must have a hard reference to the chicken though, right? Would this be more costly than interface? What would perform better?
Iâm more worried about the hardware/performance cost than picking the wrong tool for the job.
No they donât. Thatâs the whole point, they do not even need to know chickens exist.
And the interface is the slowest means of comms anyway. You canât even compare it here.
Wait. From the Unreal documentation Event Dispatchers and Delegates Quick Start Guide in Unreal Engine | Unreal Engine 5.0 Documentation :
As far as I know, if checking in the reference viewer, youâll see a hard reference to the calling blueprint. Am I missing something here?
Yes, the town actor will bind chickens & guards. They will never access one another via a reference. If you have a complex enough system, youâd have a managing class (a spawn manager) handle that kind of thing.
See the post above:
I use it with components a lot:
These 2 components can talk even though they do not reference one another.
Another undeniably cool feature of EDs is how neat can child-parent comms become:
Think of it as of autobind.
But, as @game-maker mentioned above, there is some overlap, and there will be scenarios more suitable to interface comms. If youâre building a truly modular system and do not know upfront what actor class the component will end up in - an interface would work more than fine instead, better.
You can use an intermediate actor or actor component or subsystem to break hard referencing if using event dispatches. For example make an actor component that attaches to game mode which just has all the event dispatches.
i do like 99% of my communication using event dispatches. Actually I donât use interfaces at all because I havenât found a need.
To me, event dispatch is a very future friendly way to handle communication because of the 1-to-many communication style. I can add new actors and just bind them to events, no worries. It makes for a pretty easy âfire and forgetâ system.
On a side note, i would caution new developers to not get carried away trying to avoid hard references and decoupling unless you can demonstrate why the hard-referencing is causing a problem in your project. You stand to complicate your code considerably and slow down development a lot for no good reason. Always make sure you can explain the concrete problem that actually exist in your project before committing time to making a solution for it.
I tried, but for me it doesnât work. And thereâs no tutorials out there on how to bind 2 actors through a third one that can be destroyed after. The function that I want to run in the receiving component doesnât show up.
⢠what are those components
⢠what is the event dispatcher signature
⢠what is the function signature
Destroy the one that was binding? What does after mean here? Sounds a bit like this:
aActorB
has a custom event:
when
aActorA
gets Hit, thecustom event in
aActorB
will trigger:
- the binding actor destroys itself, but the connection that was created remains intact
Thanks. The reason itâs confusing for me is because Iâm trying to bind to an actor that is not yet loaded, so that when that actor loads, it notifies whoever is listening that itâs now loaded.
I thought a âthirdâ actor would give me that option, but I realised that even that third actor has no way of binding to something thatâs not yet loaded. Am I right on this?
Very. In order to bind you need an instance to exist first.
you can do this with a manager class,
Listener binds to manager event,
new actor spawns, gets manager, calls ED and passes ref to self
One year later and I still havenât seen anyone provide a concrete example of this.
How exactly do you use a third actor to bind 100000 chickens to one (or more) town guards?
And if you then destroy that 3rd actor, are the hard references to those 100k chickens really gone? Is that really how it works?
And is that really more efficient than just binding each chicken in its own blueprint to the town guard?