-
-
Notifications
You must be signed in to change notification settings - Fork 26
Events
/!\ Under construction /!\
When coding, we often reference a script to another. For example, the MechaController script uses the Unity Rigidbody script and decides when the method function should be called. This works fine and is what is done most of the time. However, it creates a dependency between MechaController and Rigidbody, one needs the other to work. If we remove the Rigidbody script, the MechaController would not work as expected or even crash crash.
Of course, to avoid dependency, we can make the field nullable and check that it is assigned before using it. While it works, it is not very pretty. And worse, imagine a script A that relies on script B that relies on script C, which itself relies on the script A. This create a circular dependency.
This project have hundreds of file, if we are not careful, it could end up as a web with files dependent on another and another and another. And when we just wanted to test a single script, we end up forced to another 10 mores.
There are various way to tackle this problem but my favorite so far is definitely events.
The events paradigm is composed of two parts:
- The subscriber: It listens to the given event and receive a notification when the event is triggered.
- The emitter: Triggers the event. All the subscriber will receive the notification and handle the event as they wish.
To better understand events, let's make an analogy. As a user on social networks, you follow your favorite artist. When they publish a new art or song, you receive the notification because you are subscribed. If one day you decide to unsubscribe, you won't receive anything the notification if a new song is published. But other followers will! And both the artist and you will be able to keep living your life. And the best part: you can follow them again whenever you want!
Unity has its own delegate for events, called UnityEvent which has a nice editor, useful for scripts. So we are using it!
As mentioned before, to avoid dependencies, all the scripts will create a single dependency with a class called EventManager (in EventManager.cs). This class has multiple available static methods (which in fact call a Singleton).
public static void AddListener(string eventName, UnityAction listener) // subscribe to the non-typed event
public static void AddListener(string eventName, UnityAction<object> listener) // subscribe to the typed eventand its counter part
// Do nothing if there is no eventName/listener
public static void RemoveListener(string eventName, UnityAction listener)
public static void RemoveListener(string eventName, UnityAction<object> listener)These methods are used to subscribe to the given eventName. An eventName can have as many listeners as needed. There is an overload to pass additional parameters. You may have noticed the second parameter is of type UnityAction it is of type object. This is a delegate for functions of type void () and void (object). The object type is a lazy type. Basically, any class can be passed as a parameter of it. To then get the passed object as a parameter, simply cast it as (MyClass)obj. This may be dangerous as someone may not pass the expected type so we will see below how to properly do it.
When you want to trigger your events, use the following methods:
public static void TriggerEvent(string eventName) // Triggers all the non-typed events of name "eventName"
public static void TriggerEvent(string eventName, object data) // Triggers all the typed events of name "eventName"
⚠️ Depending on the overload you chose, the other type won't be triggered. The typed and non-typed events are distinct.