Creating a Notification Bus in O3DE
Feb 12, 2023
A notification bus in O3DE is like the opposite of a request bus: whereas a request bus receives events, a notification bus dispatches events.
An example of a notification bus is the InputChannelNotificationBus, which is used to receive inputs events when implementing event-driven input handling.
Requirements
A notification bus is simpler than a request bus, since it isn't responsible for actually handling events, just broadcasting them. Thus, all you really need is the interface class that defines the events that it can emit.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Then, when you want to broadcast an event, you can use the Broadcast
or Event
functions:
1 2 3 4 5 6 7 8 9 10 |
|
BroadcastResult
is used when the event handler is supposed to return something. For example, ReadyToHarvest
tells handlers that there are amount
tomatos available for harvesting, and returns the amount that was harvested by the handlers connected to the notification bus.
Some game system will calculate that there are 1234 tomatos ready to harvest, and it will broadcast an event on the TomatoHarvestNotificationBus to inform handlers. Handlers will then handle that event by overriding ReadyToHarvest
, will decide to harvest X tomatos, then return X. Finally, the game system that broadcasted that event will have access to X, to maybe decrement the harvestable_tomatos count.
What if there are multiple handlers?!
Since BroadcastResult
only returns one value, what do we do when there are multiple handlers (and thus multiple results)? That's what AZ::EBusAggregateResults
is for:
1 2 3 4 5 6 7 8 9 10 11 |
|
Events instead of Broadcasts
Since a notification bus can have multiple listeners attached to it, the Broadcast
function will send the event to all attached handlers. If you want to restrict it to a specific handler, you can use Event
, which offers an addressing system:
1 2 3 4 5 6 7 8 9 10 |
|
What exactly goes into <ID>
depends on what the notification bus's EBusTraits::BusIdType
is. Usually, it's an EntityId, so that events can be directed at specific entities. When a handler calls BusConnect()
on the notification bus, it can provide an EntityId to tell the EBus system that it wants to receive Events addressed to that EntityId.
An obvious use case for this is with Components, since Components are always tied to an Entity (and can get the EntityId by calling the member function GetEntityId()
)
Sources
- https://www.o3de.org/docs/api/frameworks/azcore/class_a_z_1_1_e_bus.html
- https://www.o3de.org/docs/user-guide/programming/messaging/ebus-design/
- O3DE source code
© Alejandro Ramallo 2024