This is one of the most useful concepts I use in my games. It’s good to implement it in early stage of prototyping. It will make your code look cleaner and increase the performance of the project. I encourage you to read the posts about events and dictionary before moving to this topic, if you are not familiar with those concepts it may be confusing for you.
This event system will be responsible for sending messages between Objects, scripts. We will use Dictionary to store UnityEvents and names of the events.
private Dictionary <string, UnityEvent> eventDictionary;
Here is the code attached to the new Empty Game object. It’s responsible for transferring massages between objects. Both Subscriber and Trigger will refer to instance of this class. In my example this will be the same object, image on the canvas.
~~~ c#
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.Collections.Generic;
public class EventSystemTest : MonoBehaviour {
private Dictionary<string, UnityEvent> eventDictionary;
private static EventSystemTest eventManager;
public static EventSystemTest instance { get { if (!eventManager) { eventManager = FindObjectOfType(typeof(EventSystemTest)) as EventSystemTest; eventManager.Init(); } return eventManager; } }
void Init() { eventDictionary = new Dictionary<string, UnityEvent>(); }
public static void StartListening(string eventName, UnityAction listener) { //We need to crate place in memory for reference to the object UnityEvent thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.AddListener(listener); } else { //If there is no event with this name add new one to dictionary. thisEvent = new UnityEvent(); thisEvent.AddListener(listener); instance.eventDictionary.Add(eventName, thisEvent); } }
public static void StopListening(string eventName, UnityAction listener) { UnityEvent thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.RemoveListener(listener); } }
public static void TriggerEvent(string eventName)
{
UnityEvent thisEvent = null;
if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
{
thisEvent.Invoke();
}
}
}
~~~
Way of getting instance of the this class by other objects is similar to Singleton pattern. There is only one instance of this class in the game scene. In this example I have only one scene so I’m not doing check conditions, to simplify the code.
~~~ c#
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class EventSubscriber : MonoBehaviour
{
void OnEnable()
{
EventSystemTest.StartListening("test", SubscribedAction);
}
void OnDisable() { EventSystemTest.StopListening("test", SubscribedAction); } void SubscribedAction() { Color color = new Vector4(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f),1f); this.GetComponent<Image>().color = color; } void Updade() { if (Input.GetKeyDown(KeyCode.Space)) EventSystemTest.TriggerEvent("test");
}
}
~~~
This script is attached to an Image on the scene. We subscribe to the Action when script is enabled, at the beginning of the game. And we need to unsubscribe the event to optimize performance of the program. To trigger an event we need just one line of code and EventManager is doing for us everything in the background.
This way even very complex relations between objects can be simplified to just few lines. We can subscribe more than one method, in different parts of game. In my example I’m triggering the event from he same script but it can be called from any other script. I’ll describe more practical use of it in next post. For more informations on this topic visit UnitySite. Stay Awesome!