Follow by Email

Friday, 7 August 2015

Unity 4.6 - Simple Tutorial, Unity Event Delegates Exposed in Editor Example


Exposing UnityEvent in the editor is much simpler than it looks! You will have the same fancy delegate event calls that the UI elements such as Buttons are having to drag and drop behaviour calls easily between your scripts! Unity Events were one of the fantastic additions to Unity 4.6, way before version 5 came to life. To my surprise, they passed very unnoticed! It's even hard to find an example that describe how to use them, not even on the official documentation!!! This is so sad that I decided to write an example myself  and try to spread the use of this fantastic feature!

UnityEvent in a custom script. Very easy and very useful! :)

So let's imagine that you have are creating a "system" for your Unity game. This "system" can be anything, from something simple like a simple timer to complicated path finding system or full featured combat engine.You want your system to be as independent as possible, that's why when important things happen you use delegates. However, delegates imply that the script that is listening for this events knows about your system at code level.

Sometimes you will want that the listener classes don't know about the notifying system neither. In the exact same way that Unity UI or NGUI work, the "links" between the classes are defined in the editor via drag and drop by the developer. Sometimes a game designer or an artist without programming skills will be doing it and then it's one of the best options.

Stop talking and let's see how it works. In this example we will have 2 simple classes.


The Sender has an UnityEvent that notifies the receiver that something happened on Start.

using UnityEngine;
using System.Collections;
using UnityEngine.Events; // You have to import this

public class Sender : MonoBehaviour{

   [SerializeField] // Serialize to show field in the editor
   public UnityEvent onStart = new UnityEvent(); // our Unity Event

   void Start () {
      onStart.Invoke(); // We invoke on start
   }
}

The Receiver is a totally normal class with a totally normal method :)

using UnityEngine;
using System.Collections;

public class Receiver : MonoBehaviour {

   public void CallMe() {
      Debug.Log("I was called");
   }
}

On the editor it looks like this:
Following the SOLID principles have never been easier! :D

Additionally, you can still add your listeners to the Unity Event to be called at the same time that the ones you added in the editor via script. This has an interesting advantage, adding them in such way ignore the limitations of the regular callbacks at the end of this post.

// This methods can have more than one parameter and have return value.
   onStart.AddListener(() => GameObject.FindObjectOfType().CallMeFloat(1.0f));
   onStart.AddListener(() => GameObject.FindObjectOfType().CallMeColor(Color.red, Color.blue));
   // After this you can call Invoke
   onStart.Invoke();
   // You can also clean the listeners
   onStart.RemoveAllListeners();
   // Note that this only removes the listeners added by code and not in the editor
}

If you want to remove a particular listener from the ones you added the things gets trickier, here you can learn more about it. Also it is important to note that using delegates in such a way kind of defeat the purpose of linking scripts in the editor and not in code. In certain cases convenience will tell you to use them like this, but raw estimations say that they are much slower than normal delegates.

All in all there is a huge reason why you should consider using Unity Events anyway... because it's a solid system that already works! No need to program it. And if you want to remove this delegates after you leave the prototype stage of your game if you want and you are free to go! :D

By the way thanks Markus for writing about how to use Unity Events! :)

Do you have any question about UnityEvents? Did you even know they exist? Do you have an amazing use case for them? See you in the comments! :)

No comments:

Post a Comment