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
EasyGive FinishLine the events the scene's rows are wired to.
- Add
using UnityEngine.Events;,public UnityEvent<int> onLap;,public UnityEvent onRaceOver;and a private int for the laps done. - In
OnTriggerEnter, whenotheris taggedPlayer, count the lap and callonLap.Invokewith the laps done. - When they reach
laps, callonRaceOver.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
1Components, Not Hierarchies
Small ComponentsA Base Enemy ScriptAbstract ComponentsComponents Working TogetherRecap: Modular TurretRecap: Twin Cannon4Serialized Data
Serializable ClassesLists in the InspectorEnums in the InspectorRecap: Loot TableRecap: Roll the Loot2Interfaces in Unity
IDamageableInterfaces and TryGetComponentGetComponentsRecap: Interact KeyRecap: Nearest in ReachPractice on your own: Unity playground