This is the line that's the crux of your question "Then iterate through all systems (all systems that can possibly handle the message)".
In reality, it depends how you register your listeners.
If you have few, or worse, only have one event type, then yes, you would be looping through most all systems. But that's the point; you don't want your systems to register to the EventSystem
for any event; this would force each system to decide for themselves if they'll handle it.
All events a system registers for are ideally events that they have to handle. If that's the case, you're iterating over exactly those systems which need to be notified anyway- event system or not. If you find that that's not the case, your events may not be granular enough (see below).
So how does having multiple event types help?
Say you allow for CameraEvent
s in your EventSystem
.
If you have a system that wants to subscribe to CameraEvent
s, it would do so by registering with your EventSystem
and saying that it's subscribing to CameraEvents
; your EventSystem
would store the system (or more likely just it's update call) in a list of listeners for specifically CameraEvent
s.
camEventListeners:List<IListener<CameraEvent>>
When an object broadcasts a CameraEvent
, the EventSystem
would only loop through all the camEventListener
s, not all listeners of all types. Essentially, only those listeners who would need to handle a CameraEvent
would be notified.
If you find that you have a lot of systems that are registering for events and then checking certain event parameters to decide whether they handle or ignore those events, your events may not be granular enough.
Imagine you have systems that only care about when a camera zooms but not when a camera pans. Clearly listening for a CameraEvent
would make for a bunch of useless calls if you have a lot of these systems that only care about zooming. In this case you may decide to break up your CameraEvent
into a CameraZoomEvent
and CameraPanEvent
and reorganize your systems to broadcast and/or listen to these more specific events.
In this scenario, your EventSystem
would then have multiple lists of listeners: one for CameraZoomEvent
listeners and one for CameraPanEvent
listeners. This can be implemented as a map in your EventSystem
.
listenerMap:Map<EventType, List<IListener<EventType>>>
When a new listener is registered, the EventMap
adds it to the correct list:
function registerListener(eventType, listener){
listenerMap.get(eventType).push(listener);
}
When a new event comes in, the EventMap
grabs the list for that EventType
and updates all the elements in that list.
function broadcastEvent(event){
// You could either use your programming language's built in type
// checker or pass in the eventType as a parameter into the broadcast event function.
for( listener in listenerMap.get(Type.typeof(event))){
listener.update(event);
}
}