While trying to decouple the various actors in my project I wonder why there’s no way to really separate and enable a clean modular approach to blueprint communication. Regardless of which blueprint communication method I choose (direct casting, interface or event dispatching) I always end up having to “target” the specific object I want to call methods or events on. Is there any way in UE4 to establish communication between objects (actors) with an event-handling “observer”-pattern style approach? I mean you can just make an event dispatcher and when firing an event, any object interested can “subscribe/unsubscribe” anonymously and receive the events that it is interested in?
Blueprint interfaces almost accomplish that, but you always have to specify the specific object you send the message to which again tightly couples the objects together and makes it impossible to make systems truly modular.
Is there a way to do this that I don’t know yet?
Yes, true! But this approach is probably very performance intensive as the engine has to send the call to every actor object and check for interface implementation?
BPIs do it ok if you specify the actor to send to as just that, actor, not the type of object it is. But you can’t do subscriber with that of course.
No, you still pick the object you want to send the call to, but the BP making the call just sees it as an actor, rather than BP-x, that could cause a tight coupling loop.
( BP-x might know about the BP type making the call ).
Blueprint interfaces almost accomplish that, but you always have to specify the specific object you send the message to which again tightly couples the objects together and makes it impossible to make systems truly modular.
It doesn’t tighly couple the objects. Yes, with interfaces, object A can “send a message” to object B, but A doesn’t know and don’t care what B is. That’s the key point. Also, A and B doesn’t need each other to work. If that’s not decoupling, then I don’t know what it’s.
Is there any way in UE4 to establish communication between objects (actors) with an event-handling “observer”-pattern style approach? I mean you can just make an event dispatcher and when firing an event, any object interested can “subscribe/unsubscribe” anonymously and receive the events that it is interested in?
There is the “Get All Actors with Interface”. So, implement the interface in the observers (“subscribe/unsubscribe”), and then use that node in any place (subject) to notify all the subscribed.
Sure, object A doesn’t know about object B when using interfaces but me as the dev I still need to somehow “glue” them together by telling A it should “target” B in some way when sending the interface message. Same thing with the event dispatcher. Or am I missing something here?? I’d like to have something like a separate “event dispatcher”-object that exists separately from A and B. I could tell A to call that event dispatcher and I could subscribe B (C, D, E etc.) to “listen” to the event dispatcher for a specific event. A and B wouldn’t know anything from each other.
I didn’t know about “Get All Actors with Interface”. Thanks for the tip! That might get me a bit closer to having a more decoupled system. Is it very expensive performance wise? The documentation says it shouldn’t be called every tick, but other than that?
I don’t know what to say. Perhaps what you want is something like the publish-subscribe pattern?
No idea if “Get All Actors with Interface” it’s expensive (I’m to lazy to check the implementation of this function).
But I can’t imagine any practical application where calling it every tick is required.
So, it’s all good.
Get All Actors with Interface doesn’t scale well since it loops through all Actors just like Get All Actors of Class.
Yes, I wish there would be a true publish-subscribe pattern already implemented in UE4.
Maybe it is possible to implement such a system in C++ in a performance sensitive way and expose it to BP?
Indeed it probably doesn’t scale well… Do you have any idea how to approach this problem and implement a decoupled publish-subscribe pattern between the actors?
Sorry, but I’m kind of struggling to understand the underlying idea. How are your actors (or the separate middle-man event dispatcher) supposed to know what events to bind to? Let’s take a banal example of two switches and two lights: to make one switch turn on one light and not the other, you have to manually connect them at some point, be that by binding to events, or indicating which actor to send an interface message to, or at least give them matching indices so that they would automatically find the respective actor to be coupled with. I just fail to understand how it would be possible to totally eliminate the need to specify concrete actors if there is more than one instance in the level.
Or am I missing something?
The difference between the observer pattern (event dispatcher in unreal) and the P-S pattern is that, while in the first you have a direct coupling between A and B, in the latter you don’t. So, the question is: how can A communicate with B? Well, you must have an intermediary service: a publish/subscribe service, which is basically a dictionary, mapping objects to events.
Implementing such a thing in BP, it’s not that hard. But the question is: why should you?
Here’s a small diagram that hopefully explains a bit better what I mean:
- Create an object called “eventService1” of type “EventService” (let’s call it something different than event dispatcher to avoid confusion with the existing event dispatcher from UE4).
- Create event inside “eventService1” and call it “toggleLight”
- Inside light1-object “subscribe” to eventService1 by calling method “subscribe” on eventService1
- Now with any kind object (here “switch1”-object) you can call the event “toggleLight” on eventService1. Any object that has subscribed to “toggleLight” will get an event “toggleLight” from eventService1 which can then be handled by the subscribing object
You could have any number of “EventServices” inside your project.
This way, only the eventService would know about the bound objects. In fact, there’s only one direct binding which is the binding between the EventService and the subscribing object that wants to receive the notification. Any object could call the event “toggleLight” on the event service. No bindings between the calling object and the eventService.
Having a system like this, we would no longer need bindings both ways like with the existing event dispatchers or with interfaces. Right now we always have to target the specific object which has the specific interface method we want to call or target the specific object before calling the event dispatcher on that object.
Do you understand what I mean?
Maybe this is easier to implement in C++ than I think… I just wonder why such a common pattern is not already implemented in UE4. It would greatly reduce dependencies between different objects.
Yes, that’s what I mean!
To be more flexible when designing event-driven systems. Every time I want to call an event on an actor I have to specifically cast to that receiving object. Lot’s of unnecessary glue code. If I change the class of the receiving object I have to change the glue code in the calling object as well.
To be more flexible when designing event-driven systems. Every time I want to call an event on an actor I have to specifically cast to that receiving object. Lot’s of unnecessary glue code. If I change the class of the receiving object I have to change the glue code in the calling object as well.
No if you use interfaces. That’s why interfaces decouples A from B. No casts needed.
But according to your diagram, both lights are subscribed to Service 1, and when the Toggle Light Event fires, both lights will be affected at the same time. That would be virtually the same that if on begin play each light Gets All Actors of Class [Switch] and subscribes to their events, and now every time you flip any switch all the lights are toggled.
How would the Event Service connect a concrete switch to a concrete light?
Hmm, maybe I’m completely missing something…
Ok, lets say we have object A as the calling object. B has interface C attached. The C interface has a method D that B implemented (via event node). A wants to call interface method D.
When A calls interface method D I have to either call “get all classes with interface C” and loop through them or cast to object B and plug in B into the “target”-pin of the interface message node. So A needs to get a reference to B to call the interface method on, therefore having a tight coupling. This is what I try to avoid.
Interesting, in the first couple of minutes of:
he says UE2 did have a way of sending to all actors, and they got rid of it :)