Skip to content

Instantly share code, notes, and snippets.

@bernardopacheco
Last active May 8, 2024 03:17
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save bernardopacheco/2b853161a9d3b8088e5f153b83342d92 to your computer and use it in GitHub Desktop.
Save bernardopacheco/2b853161a9d3b8088e5f153b83342d92 to your computer and use it in GitHub Desktop.
Unity Event Manager event-driven architecture.

Unity Event Manager

This Gist represents an event-driven architecture that helps to structure my games in Unity. It uses events to trigger and communicate between decoupled parts of a game.

Usage

In the first game scene, create an empty Game Object named EventManager and attach the EventManager.cs script to it. This script is set to DontDestroyOnLoad, i.e., it won't be destroyed when reloading scene.

The Producer.cs and Consumer.cs classes show how an event is published and consumed. In this example, when a coin is collected, an addCoins event is published with the collected amount. A Consumer receives the amount of coins collected and update its own coins amount.

Examples

  • No parameter:
EventManager.TriggerEvent("gameOver", null);
  • 1 parameter:
EventManager.TriggerEvent("gamePause", new Dictionary<string, object> { { "pause", true } });
  • 2 or more parameters:
EventManager.TriggerEvent("addReward", 
  new Dictionary<string, object> {
    { "name", "candy" },
    { "amount", 5 } 
  });
using System;
using System.Collections.Generic;
using UnityEngine;
public class EventManager : MonoBehaviour {
private Dictionary<string, Action<Dictionary<string, object>>> eventDictionary;
private static EventManager eventManager;
public static EventManager instance {
get {
if (!eventManager) {
eventManager = FindObjectOfType(typeof(EventManager)) as EventManager;
if (!eventManager) {
Debug.LogError("There needs to be one active EventManager script on a GameObject in your scene.");
} else {
eventManager.Init();
// Sets this to not be destroyed when reloading scene
DontDestroyOnLoad(eventManager);
}
}
return eventManager;
}
}
void Init() {
if (eventDictionary == null) {
eventDictionary = new Dictionary<string, Action<Dictionary<string, object>>>();
}
}
public static void StartListening(string eventName, Action<Dictionary<string, object>> listener) {
Action<Dictionary<string, object>> thisEvent;
if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) {
thisEvent += listener;
instance.eventDictionary[eventName] = thisEvent;
} else {
thisEvent += listener;
instance.eventDictionary.Add(eventName, thisEvent);
}
}
public static void StopListening(string eventName, Action<Dictionary<string, object>> listener) {
if (eventManager == null) return;
Action<Dictionary<string, object>> thisEvent;
if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) {
thisEvent -= listener;
instance.eventDictionary[eventName] = thisEvent;
}
}
public static void TriggerEvent(string eventName, Dictionary<string, object> message) {
Action<Dictionary<string, object>> thisEvent = null;
if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) {
thisEvent.Invoke(message);
}
}
}
using System.Collections.Generic;
using UnityEngine;
public class Producer : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other) {
EventManager.TriggerEvent("addCoins", new Dictionary<string, object> { { "amount", 1 } });
}
}
using System.Collections.Generic;
using UnityEngine;
public class Consumer : MonoBehaviour {
private int coins;
void OnEnable() {
EventManager.StartListening("addCoins", OnAddCoins);
}
void OnDisable() {
EventManager.StopListening("addCoins", OnAddCoins);
}
void OnAddCoins(Dictionary<string, object> message) {
var amount = (int) message["amount"];
coins += amount;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment