unity, Unity Tutorials

Delegates and Events in Unity

 delegates_events_unity

Objective:

The Objective of the tutorial is to understand how to use and implement Delegates and Events in Unity.

If you enjoyed my previous tutorial about Singletonthis is second of many tutorials to learn how to use unity to full potential and write efficient code in Unity.

Introduction :

Delegates and Events is very powerful feature of C# programming language, it helps to write efficient and clean code in unity.

Delegate :

A Delegate is a reference pointer to a method. It allows us to treat method as a variable and pass method as a variable for a callback. When it get called , it notifies all methods that reference the delegate. The basic idea behind them is exactly the same as a subscription magazine. Anyone can subscribe to the service and they will receive the update at the right time automatically.

I know at this time everything seems very confusing, just wait everything will be clear when start doing coding.

Types of Delegate:

  • Single Delegate :

    It can reference to only single method at a time.

  • Multicast Delegate :

    It can store the reference of multiple methods at a time.

Syntax :

 
//Defining Delegate
public delegate void OnButtonClickDelegate();
public static OnButtonClickDelegate buttonClickDelegate;

//Subscribing to delegate

// eg. of Singlecast 
buttonClickDelegate = myCustomMethod;

//eg. of Multicast Delegate
buttonClickDelegate += myCustomMethod;
buttonClickDelegate +=myAnotherCustomMethod

//Calling Delegates
buttonClickDelegate();

//UnSubscribing to Delegate
buttonClickDelegate -= myCustomMethod;
buttonClickDelegate -=myAnotherCustomMethod

let see this in action, Create new script named DelegateHandler and attached to empty gameobject and paste below code


using UnityEngine;
using System.Collections;

public class DelegateHandler : MonoBehaviour
{

     public delegate void OnButtonClickDelegate ();
     public static OnButtonClickDelegate buttonClickDelegate;
     
     public void OnButtonClick()
     {
       buttonClickDelegate ();
     }

}

and now create a sphere from GameObject>3D Object >Sphere and create new script named ObjectController and attached to the sphere and add below code to ObjectController class


using UnityEngine;
using System.Collections;

public class ObjectController : MonoBehaviour {

    Renderer objRenderer;
    // Use this for initialization
    void Start ()
    {
      DelegateHandler.buttonClickDelegate += ChangePosition;
      DelegateHandler.buttonClickDelegate += ChangeColor;
      objRenderer = GetComponent<Renderer>();
    }

    void ChangePosition()
    {
      transform.position = new Vector2 (transform.position.x + 2f, transform.position.y);
    }

    void ChangeColor()
    {
      objRenderer.material.color = Color.yellow;
    }

    // Unsubscribing Delegate
    void OnDisable()
    {
      DelegateHandler.buttonClickDelegate -= ChangeColor;
      DelegateHandler.buttonClickDelegate -= ChangePosition;
    }

 }

 

now in the inspector attach button event to the DelegateHandler  “OnButtonClick” method and click play. You will see it will call are assigned method if we click on the button. In this manner, any class can subscribe to OnButtonClickDelegate and get a callback, when this gets called.I hope it make some sense now.

But this implementation prone to error, as we discussed earlier there are two types of delegates, so if we use singlecast delegate options after multicast delegate, it will reset the existing invocation method list.

Now create a new method ChangeRotation and change the start method of  ObjectController Class as below.

    void Start ()
    {
      DelegateHandler.buttonClickDelegate += ChangePosition;
      DelegateHandler.buttonClickDelegate += ChangeColor;
      Delegatehandler.buttonClickDelegate = ChangeRotation;
      objRenderer = GetComponent ();
    }

and run the unity, you will notice now ChangePosition and ChangeColor will not get called,only ChangeRotation code will run, this is because, assign operator will reset the existing invocation list, this situation is very difficult to track if multiple classes subscribe to same delegate, to avoid this situation, we use Events.

Events :

Events adds a layer of abstraction and protection on delegate, this protection prevents client of the delegate from resetting the delegate and invocation list. Events only allow to add and remove method from invocation list.

Change the DelegateHandler class as below


using UnityEngine;
using System.Collections;

public class DelegateHandler : MonoBehaviour
{

     public delegate void OnButtonClickDelegate ();
     public static event OnButtonClickDelegate buttonClickDelegate;
     
     public void OnButtonClick()
     {
       buttonClickDelegate ();
     }

}

now if you go to unity, it will show error message “The event `DelegateHandler.buttonClickDelegate’ can only appear on the left hand side of += or -= when used outside of the type `DelegateHandler”.

just change the start method as below to remove the error, don’t forget to unsubscribe in OnDisable method, otherwise, it will leak memory.

//
Delegatehandler.buttonClickDelegate += ChangeRotation;
//

I hope now you have the better understanding of Delegate and Events.

Conclusion :

  • Delegates and Events help us to write modular and reusable code.
  • Always use Events together with Delegates for safety.
  • Do not forget to unsubscribe otherwise, it will lead to memory leak.

Please let me know if you have any query, or if you have any view on this topic.

8 comments

  1. h4ri

    It is pure C#. In Unity3D there is a bult-in class: UnityEvent. While the C# delegates and events are not complicated, maybe UnityEvent makes little easier and readable the code.

    1. UG Post author

      you are right h4ri, you can use UnityEvent instead of Delegates and Events,this post explains very well why we should use C# Events than UnityEvents

      1. h4ri

        Sorry, I didn’t get the point why I shouldn’t use UnityEvent, in the article it’s not even mentioned. Using the delegates and events maybe a little faster, after all, the UnityEvent using it in the same way, it’s only an abstraction layer on it, but the Unity guys done some things, so it is serialized (so you can use it from the hierarchy, and it’s a good thing), straightforward, etc.

        By the way, I don’t argue with the content of the article, it’s really good. I just only say, if Unity3D, then using UnityEvent is a good thing 🙂

        1. UG Post author

          No doubt UnityEvents simplify the whole process, planning to write UnityEvent post soon

  2. Pingback: The week in .NET – 8/2/2016 | .NET Blog

  3. Pingback: [Unity] Event와 Delegate | yoronge

  4. majak the coder

    It is also a good idea to use System.Action delegate instead of defining your own delegates every time.

    1. eskivor

      System.Action, that’s exactly what I current use for my delegates 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *