Events Drive the UI
Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 15 of 64.
With events, the HUD follows the game while the game knows nothing of the HUD. This Health owns the hit points and announces two things: the health changed, and it reached 0. It has no field for a bar, a text or a game-over screen, so the same component works on the player, on an enemy that has no HUD, and in a test scene:
public class Health : MonoBehaviour
{
public int maxHp = 100;
public event Action<int, int> OnChanged;
public event Action OnDied;
public int Hp { get; private set; }
void Awake()
{
Hp = maxHp;
}
public void TakeDamage(int amount)
{
if (Hp == 0) return;
Hp = Mathf.Max(Hp - amount, 0);
OnChanged?.Invoke(Hp, maxHp);
if (Hp == 0) OnDied?.Invoke();
}
}// HealthBar.cs, on the HUD
public Health health;
public Image bar;
void OnEnable() { health.OnChanged += Show; }
void OnDisable() { health.OnChanged -= Show; }
void Start()
{
Show(health.Hp, health.maxHp);
}
void Show(int hp, int max)
{
bar.fillAmount = (float)hp / max;
}The bar listens only while it is active, with the OnEnable and OnDisable pair. The event passes both numbers, so Show needs nothing else from the Health. A GameOverScreen subscribes to OnDied to show its panel and a hurt sound subscribes to OnChanged, each in its own script, and the Health does not change for any of them. Hp { get; private set; } lets the HUD read the health but not change it.
An event reports changes, so before the first hit the bar has heard nothing. It draws the current health once, in Start. Not in OnEnable: Unity calls Awake and then OnEnable object by object, in no promised order, so the bar's OnEnable can run before the Health's Awake has set Hp, and the bar would show 0. By the time any Start runs, every Awake has run.
Challenge
EasyMake the gun announce its changes and the HUD listen.
- In
Gun.cs, addusing System;,public event Action<int, int> OnAmmoChangedandpublic event Action<bool> OnReloading; raise them where the comments say. - In
AmmoHud.cs, subscribe inOnEnable, unsubscribe inOnDisable:ammoTextshowsAmmo: 4/6, andreloadTextshows only while reloading. - In
Start, drawgun.Ammoandgun.Reloadingonce.
Press Play and empty the gun twice. Then Check.
Try it yourself
using UnityEngine;
using TMPro;
public class AmmoHud : MonoBehaviour
{
public Gun gun;
public TMP_Text ammoText;
public GameObject reloadText;
}
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 Reach3Events
C# Events in UnitySubscribe in OnEnableUnityEvent FieldsEvents Drive the UIRecap: Achievement PopupRecap: Popup TimerPractice on your own: Unity playground