What is Event Delegation?
“…a helper object, known as a delegate, is given the responsibility to execute a task for the delegator“
– Delegation Pattern Wikipedia
Why use Event Delegation?
A good practice when working with Unity (or any framework) is to decouple your UI logic from your game logic. It’s fine to have the UI code reach down to the game logic layer and call methods directly on it but having the game logic layer directly call methods on the UI logic’s layer is, in general, a bad practice because doing so “marries” you to whatever UI you are currently using. So to get around this we can use C#’s Delegates and Events to fire off methods throughout our UI and even on the game logic layer.
How to use Event Delegation with Unity
All we have to do is:
- create a static Event Manager class
- Add delegates and events to this Event Manager
- Listeners will add functions to the events
- Delegators will fire off the events
The Manager: Defining events
public class EventManager { public delegate void EnemyHovered(int laneIndex, int targetRange); public static event EnemyHovered EnemyTargetedRequest; public static void EnemyTargeted(int laneIndex, int targetRange) { if(EnemyTargetedRequest != null) EnemyTargetedRequest(laneIndex, targetRange); } }
In this example we create a delegate with the type EnemyHovered which takes the arguments laneIndex and targetRange. Then we make an event EnemyTargetRequest which is the event that the listeners will subscribe functions to. Finally, there is a static method that can be called by delegators when they want to fire off this event, triggering all the functions that are subscribed to it.
The Listener: Subscribing to the event
In another class we can add the following:
void Awake() { EventManager.EnemyTargetedRequest += DoSomething; } public void DoSomething(int targetedIndex, int targetRange){ // do something }
In this class we define some function called DoSomething that takes the same arguments as our delegate. In the Awake() method we add the function to the static class’s EnemyTargetedRequest event.
The Delegator: Firing off events
In yet another class we can do the following:
public void OnPointerEnter(PointerEventData eventData) { EventManager.EnemyTargeted(_index, _targetCount); }
Here we’re just using Unity’s OnPointerEnter event as the UI event that will trigger our EnemyTargeted event. Because our Listener class subscribed it’s DoSomething function to the EnemyTargetRequest event when SignalManager.EnemyTargeted is called it will fire off the DoSomething function!
So with this, you can keep all your events off in the static Event Manager, subscribe to them when you need an object to react to an event and fire off the events whenever you need to which allows you to keep UI and game logic separated. You could even have GameObjects subscribe to events and unsubscribe from them as they are created and destroyed which is very useful when these objects are created and destroyed dynamically.