Delegates in Unity
Delegates
A feature of C# that allows assigning a function to a variable. The function can then be called using the variable.
This can be used to implement the Observer programming pattern where there are subscribers that carry out actions when intimated by publishers.
Defining Delegates
1. Declare the signature of the Delegate
delegate void MyDelegate();
2. Declare an instance of the Delegate
MyDelegate OnTakeDamage;
The Delegate signature is a reference for the return type and parameters of the Delegate. Functions that are to be assigned to the Delegate must have similar signature.
The Delegate instance is assigned a function.
OnTakeDamage = reduceHealth;
The Delegate is called which in turn executes the function.
OnTakeDamage();
However it is necessary to check if a function is assigned to the Delegate, else it raises the null reference error.
OnTakeDamage?.Invoke();
( ?. => null-conditional operator )
using System.Collections
using System.Collections.Generic;
using UnityEngine;
using System;
public class ActionScript : MonoBehaviour
{
public delegate void MyDelegate();
public static event MyDelegate OnTakeDamage;
void Start()
{
OnTakeDamage = reduceHealth;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
OnTakeDamage?.Invoke();
}
}
void reduceHealth()
{
Debug.Log("Health got reduced!");
}
}
Parameters and return types can be defined when declaring the Delegate
delegate void MyDelegate(int);
MyDelegate OnTakeDamage;
OnTakeDamage?.Invoke(5);
Delegates can be made to trigger functions in other scripts by making the access modifier public. Having the static keyword lets us access the Delegate with the class name itself.
Recommended by LinkedIn
Player.OnTakeDamage = reduceHealth;
Delegates can be multicast, which means a single delegate can be made to trigger multiple functions.
Player.OnTakeDamage += reduceHealth;
Player.OnTakeDamage += updateHealthBar;
Here, both reduceHealth() and updateHealthBar() get called when OnTakeDamage is invoked. It is also important to unsubscribe from the Delegates when the subscriber object becomes inactive.
Player.OnTakeDamage -= updateHealthBar;
Events
Having public delegates has its cons. The delegate can be modified or even set to null by any script.
Hence we have Events. Events are special delegates that can only be invoked by its own class.
Defining events
1. public delegate void MyDelegate();
2. public static event MyDelegate OnTakeDamage;
Action is a pre-built Delegate that has void return type and can pass parameters. They don't require describing the signature of the delegate.
public static event Action OnTakeDamage;
public static event Action<bool,int> OnTakeDamage;
Func is another type of pre-built Delegate that has a return type and can pass parameters.
public static event Func<out,in> OnTakeDamage;
UnityEvents are similar to delegates, but they are serializable, which means they can be modified in the Unity Inspector.
using System.Collections
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System;
public class ActionScript : MonoBehaviour
{
public UnityEvent OnTakeDamage;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
OnTakeDamage?.Invoke();
}
}
public void reduceHealth()
{
Debug.Log("Health got reduced!");
}
}
Delegates and Events can be useful in making scripts modular. Meaning the functions corresponding to certain use cases can all be placed within the same class, and delegates can be used to indicate events to trigger specific functions. This can help organize code and define clear action triggers and responses.
01-10-2022