Tag Archives: events

Easy to manage event system in C# and Unity3d

.NET has a really nice event callback system that works great with Unity3d. This is important for a few reasons:

  • Performance: Checking and running code through Update on every game object every frame can bogg down the application cpu thread.
  • Organization: Using component based design, it is best to keep each component self contained. It can be easy to get in a tangled mess adding references all over different game objects to work together.
  • Disabled Objects: Unity doesn’t run code on disabled objects and has strange behavior when trying to use a standard Constructor. This method works on disabled objects, allowing you to enable them on an event for example.

This is the event handler class:

public class GameEvent : MonoBehaviour
{
    // Add events to this enum as needed
    public enum Type
    {
        GameStart,
        GameEnd,
        Win,
    };

    private GameEventListener[] m_listeners = null;
    public delegate void Handler(Type e);
    public static event Handler Callback;

    // Collect all listeners on startup
    void Awake()
    {
        m_listeners = Resources.FindObjectsOfTypeAll<GameEventListener>();

        foreach (GameEventListener listener in m_listeners)
            listener.AddCallback(ref Callback);
    }

    // Cleanup all listeners on shutdown
    void OnDestroy()
    {
        foreach (GameEventListener listener in m_listeners)
            listener.RemoveCallback(ref Callback);
    }

    // Call this to trigger events
    public static void Trigger(Type e)
    {
        Callback(e);
    }
}

To issue events, just call GameEvent.Trigger with the event type as the parameter. Then on game objects that need to listen and respond to events:

public abstract class GameEventListener : MonoBehaviour
{
    public void AddCallback(ref GameEvent.Handler callback)
    {
        callback += new GameEvent.Handler(OnGameEvent);
    }

    public void RemoveCallback(ref GameEvent.Handler callback)
    {
        callback -= new GameEvent.Handler(OnGameEvent);
    }

    protected abstract void OnGameEvent(GameEvent.Type e);
}

Just extend from GameEventListener for your own classes to be able to listen and respond to events, like so:

class ExampleListener : GameEventListener
{
    protected override void OnGameEvent(GameEvent.Type e)
    {
        if (e == GameEvent.Type.GameStart)
        {
            // Custom event response code here
        }
    }
}

The only drawback of this method is that objects that extend from GameEventListener cannot use Unity coroutines because of GameEventListener being abstract and messing with how Unity backend of Monobehavior works. This can be solved by using a thread pool. Or, if you need coroutines just implement the methods from GameEventListener in a class extended from MonoBehaviour. The reason GameEventListener is abstract is because extended objects would otherwise not be able to receive events when they are disabled because of how MonoBehavior prevents code running on disabled objects.