One of the best ways to handle events in Unity is... using UnityEvents!
In this example, we have a singleton called TurnManager
with functions we can call when a turn starts or ends. Units subscribe to the relevant event so they are notified when a turn starts or ends.
public class TurnManager : MonoBehavior {
//singleton pattern for convenience
private static TurnManager instance;
public static TurnManager Instance => instance;
[SerializeField] private UnityEvent onTurnStart;
public UnityEvent OnTurnStart => onTurnStart;
[SerializeField] private UnityEvent onTurnEnd;
public UnityEvent OnTurnEnd => onTurnEnd;
void Awake() {
Assert.IsNull(instance);
instance = this;
}
void OnDestroy() {
instance = null;
}
public void StartTurn() {
onTurnStart.Invoke();
}
public void EndTurn() {
onTurnEnd.Invoke();
}
}
public class SelfHealingUnit : Unit {
[SerializeField] private int hpPerTurn = 10;
void OnEnable() {
TurnManager.Instance.OnTurnStart.AddListener(TurnStartHandler);
}
void OnDisable() {
TurnManager.Instance.OnTurnStart.RemoveListener(TurnStartHandler);
}
void TurnStartHandler() {
HP += hpPerTurn;
}
}
public class SuicideUnit : Unit {
[SerializeField] private int lifespan = 3;
[SerializeField] private UnityEvent onExplode;
public UnityEvent OnExplode => onExplode;
int turnsAlive = 0;
void OnEnable() {
TurnManager.Instance.OnTurnEnd.AddListener(TurnEndHandler);
}
void OnDisable() {
TurnManager.Instance.OnTurnEnd.RemoveListener(TurnEndHandler);
}
void TurnEndHandler() {
turnsAlive++;
if (turnsAlive >= lifespan) {
Explode();
}
}
public void Explode() {
//do stuff here
//...
onExplode.Invoke();
}
}
This way we don't have to notify every single unit every time the turn starts or ends; we only notify the units that care when the turn starts or ends. You can easily extend this example with other types of events.