Menu
CoddyTech

UnityEvent Fields

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 14 of 64.

A Button's On Click () is a UnityEvent field, and your own scripts can have one too. A public UnityEvent field shows in the Inspector as the same kind of list, and the script raises it with Invoke() without knowing what is wired to it. This countdown ticks once a second:

using UnityEngine;
using UnityEngine.Events;

public class Countdown : MonoBehaviour
{
    public int seconds = 3;
    public UnityEvent<int> onTick;
    public UnityEvent onFinished;

    void Start()
    {
        InvokeRepeating("Tick", 1f, 1f);
    }

    void Tick()
    {
        seconds--;
        onTick.Invoke(seconds);
        if (seconds == 0)
        {
            CancelInvoke("Tick");
            onFinished.Invoke();
        }
    }
}

In the Inspector, On Finished () takes rows like a button's: one row launches the rocket, another opens the gate. Another level reuses the same Countdown with other rows, and nobody writes a new script. UnityEvent<int> passes a value. In its dropdown a method that takes an int is listed under Dynamic int, and that row gets the value given to Invoke, here the seconds left. The same method under Static Parameters gets a number typed into the row instead, and methods with no parameter can be wired as well.

Unity creates a UnityEvent field when it loads the script, so onTick is never null and needs no ?., and code can add listeners with onTick.AddListener(ShowSeconds). Choose a UnityEvent when the reaction differs from object to object and is set up in the Inspector, by you or by a designer who never opens the script. Choose a C# event when code listens: the compiler checks the method names, so a rename breaks the build instead of leaving a quiet <Missing> row, and a C# event never shows in the Inspector.

challenge icon

Challenge

Easy

Give FinishLine the events the scene's rows are wired to.

  1. Add using UnityEngine.Events;, public UnityEvent<int> onLap;, public UnityEvent onRaceOver; and a private int for the laps done.
  2. In OnTriggerEnter, when other is tagged Player, count the lap and call onLap.Invoke with the laps done.
  3. When they reach laps, call onRaceOver.Invoke(); after that, crossing does nothing.

Press Play and drive three laps. Then Check.

Try it yourself

using UnityEngine;

public class FinishLine : MonoBehaviour
{
    public int laps = 3;

    void OnTriggerEnter(Collider other)
    {
        // the car crossed the line: one more lap done
    }
}

All lessons in Game Architecture in Unity

Practice on your own: Unity playground