Tuesday, July 21, 2020

Delegate vs Event C#

http://www.unitygeek.com/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 :

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//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
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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.
?
1
2
3
4
5
6
7
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
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
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 errordon’t forget to unsubscribe in OnDisable method, otherwise, it will leak memory.
?
1
2
3
//
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.

No comments:

Post a Comment