What is a Delegate?
A delegate is a type that allows you to store and pass functions like variables. Similar to function pointers, you can store a function to call later and execute it when needed.
Basic Concepts
- Function Reference Storage: Store functions in variables
- Call Later: Execute stored functions at desired times
- Polymorphism: Connect various functions using the same delegate type
Delegate Declaration
// Delegate type declaration
public delegate void MyDelegate();
// Delegate with parameters
public delegate void MyDelegateWithParam(string message);
// Delegate with return value
public delegate int MyDelegateWithReturn(int a, int b);
Basic Example
using UnityEngine;
// Delegate type declaration
public delegate void SimpleDelegate();
public class DelegateExample : MonoBehaviour
{
void Start()
{
// Create delegate variable
SimpleDelegate myDelegate;
// Assign function to delegate
myDelegate = SayHello;
// Invoke delegate (execute function)
myDelegate(); // Outputs "Hello!"
}
void SayHello()
{
Debug.Log("Hello!");
}
}
Delegate with Parameters
public delegate void MessageDelegate(string message);
public class DelegateWithParam : MonoBehaviour
{
void Start()
{
MessageDelegate myDelegate = PrintMessage;
myDelegate("Learning Unity!"); // Outputs "Learning Unity!"
}
void PrintMessage(string msg)
{
Debug.Log(msg);
}
}
Delegate with Return Value
public delegate int CalculateDelegate(int a, int b);
public class DelegateWithReturn : MonoBehaviour
{
void Start()
{
CalculateDelegate calc = Add;
int result = calc(5, 3); // Returns 8
Debug.Log(result);
}
int Add(int a, int b)
{
return a + b;
}
}
Multicast Delegate
What is a Multicast Delegate?
You can connect multiple functions to a single delegate and execute all of them with one call.
Basic Usage
public delegate void MultiDelegate();
public class MulticastExample : MonoBehaviour
{
void Start()
{
MultiDelegate myDelegate;
// Add first function
myDelegate = FirstFunction;
// Connect additional functions with += operator
myDelegate += SecondFunction;
myDelegate += ThirdFunction;
// One call executes all functions
myDelegate();
// Output:
// "First function executed"
// "Second function executed"
// "Third function executed"
}
void FirstFunction()
{
Debug.Log("First function executed");
}
void SecondFunction()
{
Debug.Log("Second function executed");
}
void ThirdFunction()
{
Debug.Log("Third function executed");
}
}
Removing Functions
void Start()
{
MultiDelegate myDelegate = FirstFunction;
myDelegate += SecondFunction;
myDelegate += ThirdFunction;
// Remove function with -= operator
myDelegate -= SecondFunction;
myDelegate(); // Only FirstFunction and ThirdFunction execute
}
Null Check
void Start()
{
MultiDelegate myDelegate = null;
// Check null before calling (important!)
if (myDelegate != null)
{
myDelegate();
}
// Or simply
myDelegate?.Invoke();
}
Practical Usage Examples
Example 1: Callback Function
public delegate void OnCompleteDelegate();
public class TaskManager : MonoBehaviour
{
public OnCompleteDelegate OnTaskComplete;
void Start()
{
OnTaskComplete += ShowMessage;
OnTaskComplete += SaveProgress;
// When task completes
CompleteTask();
}
void CompleteTask()
{
// Task completion logic...
// Invoke callback
OnTaskComplete?.Invoke();
}
void ShowMessage()
{
Debug.Log("Task completed!");
}
void SaveProgress()
{
Debug.Log("Saving progress");
}
}
Example 2: Conditional Function Execution
public delegate bool ConditionDelegate(int value);
public class ConditionalExample : MonoBehaviour
{
void Start()
{
ConditionDelegate check = IsPositive;
if (check(10))
{
Debug.Log("Positive number");
}
}
bool IsPositive(int value)
{
return value > 0;
}
}
Notes
- Null Check: Always check for null before invoking delegates
- Memory Leaks: Functions connected to delegates maintain references, so remove them when not needed
- Multicast: All connected functions execute when multiple functions are connected
Practical Tips
Tip 1: Null Check Pattern
// ✅ Safe invocation
myDelegate?.Invoke();
// Or
if (myDelegate != null)
{
myDelegate();
}
Tip 2: Delegate Initialization
// Initialize delegate with empty function to avoid null checks
public delegate void MyDelegate();
MyDelegate myDelegate = () => { }; // Initialize with empty lambda function
Tip 3: Using Action and Func
using System;
// Action: Delegate without return value
Action<string> printAction = Debug.Log;
printAction("Hello");
// Func: Delegate with return value
Func<int, int, int> addFunc = (a, b) => a + b;
int result = addFunc(5, 3);