DEV Community

Cover image for Using C# Delegates in Unity
Game Dev 4K
Game Dev 4K

Posted on

Using C# Delegates in Unity

First, let's talk about the use case.

I'm building a game where there's a freeze action. When the game is in the freeze mode, I want to notify other game objects. So, they can act accordingly.

Check this demo:

Try Unity C# Delegates Demo

That's where c# delegates come handy.

Event Manager

Usually, you need to have a place to register events. So, other game objects can register and listen to events. In my app, we have a class called GameConfig like this:
(There are more code in this class, but I removed them for clarity)

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class GameConfig : MonoBehaviour
{
    public delegate void FreezeChangeHandler(bool isFreezed);
    private FreezeChangeHandler freezeHandlers;

        public static GameConfig current;

    void Start()
    {
            GameConfig.current = this;
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void OnFreezeChange(FreezeChangeHandler e)
    {
        freezeHandlers += e;
    }

    public void OffFreezeChange(FreezeChangeHandler e)
    {
        if (freezeHandlers == null) return;
        freezeHandlers -= e;
    }

    public void Freeze()
    {
        freezeHandlers?.Invoke(true);
    }

    public void UnFreeze()
    {
        freezeHandlers?.Invoke(false);
    }
}
Enter fullscreen mode Exit fullscreen mode

It seems like a lot, but let me explain each of these in detail.

public delegate void FreezeChangeHandler(bool isFreezed);
Enter fullscreen mode Exit fullscreen mode

Here we are defining a delegate. It's a custom type for a function signature. In this case, we define a delegate for a function that accepts a boolean and returns nothing.

private FreezeChangeHandler freezeHandlers;
Enter fullscreen mode Exit fullscreen mode

Here we defined a variable for keeping handlers(function) of our delegate. If you didn't get what this will do, don't worry. You will understand in a bit.

public void OnFreezeChange(FreezeChangeHandler e)
{
    freezeHandlers += e;
}
Enter fullscreen mode Exit fullscreen mode

This is a public function in our class, which other games objects register handlers. By doing that, they can get notified when there's a change in our app's freeze state.

See. The first argument of this function is our delegate. So, we can call this function with a function as the argument.
(We can see that in a bit)

public void OffFreezeChange(FreezeChangeHandler e)
{
    if (freezeHandlers == null) return;
    freezeHandlers -= e;
}
Enter fullscreen mode Exit fullscreen mode

This is similar to the previous one, but for removing the handler. Here, we need to check for freezeHandlers to be not null because it cannot remove anything if there are no such items inside it.

public void Freeze()
{
    freezeHandlers?.Invoke(true);
}

public void UnFreeze()
{
    freezeHandlers?.Invoke(false);
}
Enter fullscreen mode Exit fullscreen mode

Finally, we have two functions to notify (or call) these handlers. In my app, we have two functions like this. But in your app, it could be based on some user input or similar.

What you need to know is how we can call these handlers like this:

reezeHandlers?.Invoke(true);
Enter fullscreen mode Exit fullscreen mode

Register Handler

Now we can register a handler for this delegate like this:

using System;
using System.Collections;
using UnityEngine;

public class Drop : MonoBehaviour
{
    void Start()
    {
        GameConfig.current.OnFreezeChange(WithFreezeChange);
    }

    private void OnDestroy()
    {
        GameConfig.current.OffFreezeChange(WithFreezeChange);
    }

    private void WithFreezeChange(bool isFreezed)
    {
        // Do something with the state change
    }
}
Enter fullscreen mode Exit fullscreen mode

Let me explain each of these code blocks:

private void WithFreezeChange(bool isFreezed)
{
    // Do something with the state change
}
Enter fullscreen mode Exit fullscreen mode

The above function is our handler for the event. It has a signature that is similar to our delegate; it accepts a boolean & returns nothing.

void Start()
{
    GameConfig.current.OnFreezeChange(WithFreezeChange);
}
Enter fullscreen mode Exit fullscreen mode

Then we will register our handler by getting an instance of our game config.

private void OnDestroy()
{
    GameConfig.current.OffFreezeChange(WithFreezeChange);
}
Enter fullscreen mode Exit fullscreen mode

We also need to remove the handler when the game object is destroying. Otherwise, it will lead to errors and memory issues.

Example

Thanks for reading up to here 🙏.
Have a look at this example game to see this in practice.

Top comments (0)