Menu
CoddyTech

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 icon

Challenge

Easy

Make the gun announce its changes and the HUD listen.

  1. In Gun.cs, add using System;, public event Action<int, int> OnAmmoChanged and public event Action<bool> OnReloading; raise them where the comments say.
  2. In AmmoHud.cs, subscribe in OnEnable, unsubscribe in OnDisable: ammoText shows Ammo: 4/6, and reloadText shows only while reloading.
  3. In Start, draw gun.Ammo and gun.Reloading once.

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

Practice on your own: Unity playground