Function Override vs Interface vs Event Dispatcher

I’ve had a good search and haven’t found this specifically discussed anywhere so I though I might bring it up. I’ll start with a simple example.

Say we have a BaseActor and a DerivedActor that inherits from BaseActor. In the character blueprint, I would like to call a function from the BaseActor that could possibly be overridden by the DerivedActor. So the most obvious choice would be to add a function to the BaseActor and allow the DerivedActor to override it if needed. The character blueprint can then call the function on an instance of the actor in question.

I’ve recently been reading more about interfaces and event dispatchers, so I thought I’d apply them both to this simple example just to see how the implementation differs.

With an interface, I first have to create a Blueprint Interface with the desired function it in. Then in the BaseActor and/or the DerivedActor I can respond to the interface event when it is triggered on the Event Graph. The character blueprint can then call the interface function on an instance of the actor in question, just like calling a normal function.

With an event dispatcher, I first create the event dispatcher on the BaseActor. Then on the Event Graph of the BaseActor and/or the DerivedActor I can bind a function to the event that is called when the event is triggered. The character blueprint can then call the event dispatcher message on an instance of the actor in question, just like calling a normal function.

In conclusion. After trying out all three implementations for this simple example, it appears as though a simple Function Override is the way to go. The other two methods achieve the same result, but require more set up and don’t appear to offer any significant advantages. Do you think this is sound reasoning or am I missing something?

I would also be interested in hearing other people’s opinions on these options as I would really like to gain a deeper understanding of when each of these methods of implementation would be appropriate use.

Monitoring for responses.

BP Interfaces and dispatchers exist only to facilitate communication between two classes that are unrelated to each other.
There’s no reason to interface or dispatch to a class that is a child of your base blueprint, overridable functions are enough if you don’t need communication between 2 actors.

i think the dispatcher is intended for when you want someone else to react to something that happens in the actor. for example, you might make a generic “button” blueprint with a “pressed” event dispatcher, and then in the level blueprint you set it up so the “open” function on a door gets called when the event dispatcher of a specific button instance in the level is triggered.

this way the button doesn’t need to know about the door and the door doesn’t need to know about the button. only the level blueprint would know both, and you could trigger the door with lots of other unrelated things, like after a bossfight is won, or whatever.

the interface is useful when you can’t use normal inheritance. for example, let’s say you’re making one of those games where the E-key uses things in the world. you have a lever you can pull, and an NPC you can talk to. the lever might just inherit from Actor, while the NPC is a Character. Nowhere to inject you own “UseableThingy” class in the hierarchy, so you can use an interface instead.

So if your level had 100 doors and 100 buttons, each opening one corresponding door, does that mean the level blueprint would have to have all 100 button dispatcher events on its event graph, with each one wiring up to the Open function of a door?

Ok this is interesting. I will be facing this exact scenario. At the moment I have created an actor that can respond to pressing the E key. Then I just derive from that actor to get specific functionality for other actors. I completely forgot about the case of also interacting with an NPC. They of course will be a character and therefore cannot derive from my custom actor. So now I can see a valid case for interfaces if I’m understanding this correctly.

The easiest is get all actors of class

They each have advantages in different use cases.

This is probably the optimal thing to do if a) you want to guarantee that all classes have some default implementation of the function/event, and b) only children of BaseActor (or at least, few other classes) need to have the function available.

This is correct except that to be clear, the Interface only has the function *signature *(and return values), not an implementation of the function itself. This is useful if you want to be able to call the same function on classes that don’t necessarily inherit from each other.

E.g, if you want to have an “Interact” function on both a LightSwitchActor that derives from Actor and an NPC class that derives from Character, you could create an Interface with an “Interact” function, then have each of those classes implement them. At runtime, you would grab references to them as Actor objects (since they all inherit from Actor) and then call the Interface function, which will fail silently if the object doesn’t implement the interface. If you tried implementing “Interact” directly on each of the two classes, you’d have to cast them to the correct type before calling “Interact,” which can get very ugly as the number of implementing classes increases.

This isn’t really what dispatchers were designed for, imo. In this example, there’s no advantage of using a dispatcher rather than a regular event/function.

The main advantage of a dispatcher is that it enables an object X to call events on multiple objects A, B, C, … etc. without needing references to those objects or even “knowing” what those will be until runtime. For example, maybe you have many dynamically-spawned NPCs whose behavior should change when the player dies. You could either:

A. Implement an “OnDeath” event on the player BP that searches for all NPC objects and calls the “ChangeBehavior” event on each of them; or
B. Implement an “OnDeath” event dispatcher and have each NPC object bind its own “ChangeBehavior” event to it when it’s spawned

With A, the player object needs to get a reference to every NPC in the level. With B (the event dispatcher), the player object doesn’t need a reference to any of the NPCs, but the NPCs need a reference to the player object (which they probably have anyway for other functionality, or they can get easily using GetPlayerCharacter()). B resembles an Observer Pattern, which seems to be what event dispatchers were designed for.

1 Like

When I originally read about Interfaces and dispatchers I thought they were so cool, until you read how you have to have a reference. For example:

You have 2 Actor Blueprints in a level.

  1. ActorA is the brain that control all the other actors.

  2. ActorB is the car.

When the car is possessed or other things happen the car need to communicate with the brain and change variables. The only way for the car to communicate with the brain is to get a reference to the brain, even using interface or dispatcher you have to get a reference to the brain. There is no way for the vehicle to broadcast a message and for the brain to be listening.

Does anyone know of a way for the car actor BP to communicate to the brain actor BP without having a direct reference?

After thinking about this for a week now I have come to the conclusion that both the event dispatcher and interfaces are out dated and need to be deprecated. If you need to talk with an actor just use get all actor of class or if you need to indirectly talk to an actor that you do not have a reference to just create a variable in the Game Instance.

Event dispatchers and interfaces serve a very specific purpose and is by no means obsolete.

Event dispatchers implements the observer pattern where any number of objects can observe a specific object event. The observed object doesn’t need a reference to the observers as it is handled by the event dispatcher (delegate).

Interfaces decouples objects by implementing an interface. Unlike direct communication where you need a specific class reference in order to call a specific function you can simply use any type of reference and attempt to call the interface function. If the object implements the interface the function is called otherwise the call is silently dropped.

The car doesn’t need a reference to the brain if the dispatcher is on the car and the brain is binding to it (also called observing).

“Get all actors of class” can be a slow operation and should be used sparingly.

1 Like

Anytime you create a dispatcher you have to get reference. I think event dispatchers should work like tags, you add it to your BP and then when anything calls that dispatcher any BP that has it added will respond. The way it is now you still have to get references.

Without a reference how would you determine which object the Event Dispatcher you want to observe belongs to?

You would have to have unique tags for every object

tag
OpenDoor1
OpenDoor2
OpenDoor3
etc.

Tags can be useful occasionally but can easily break since they are not evaluated at compile time.

I don’t think so. If you think about it from a high level, you would always need to get a reference of the actor that you want to communicate to, or how else would the program know what actor to deal with?

Back to the interface question. Yes, you still need to get a reference, but you don’t need to know the class type! Using the example above of a game that you interact with the world by pressing E key, without interfaces you would need to try to cast this reference to every possible interactable class just to call its interact function. With interfaces, you call the function on this interface, and the corresponding implementation for this class will be executed without casting.