Menu
CoddyTech

イベントでUIを動かす

CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 15/64。

イベントを使うと、HUDはゲームの状態に追従し、ゲーム側はHUDについて何も知りません。このHealthはヒットポイントを管理し、2つのことを通知します。体力が変化したことと、0に達したことです。バーやテキスト、ゲームオーバー画面のフィールドを持たないため、同じコンポーネントをプレイヤーにも、HUDのない敵にも、テストシーンにも使えます。

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、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;
}

バーは、OnEnableとOnDisableの組み合わせによって、有効になっている間だけイベントを監視します。イベントは2つの数値を渡すため、ShowはHealthからほかの情報を受け取る必要がありません。GameOverScreenはパネルを表示するためにOnDiedを購読し、ダメージ音はOnChangedを購読します。それぞれ別のスクリプトで処理され、Healthはどちらのためにも変更されません。Hp { get; private set; }を使うと、HUDは体力を読み取れますが、変更はできません。

イベントは変化を通知するため、最初の攻撃を受けるまではバーには何も通知されません。バーはStartで現在の体力を一度描画します。OnEnableでは描画しません。UnityはオブジェクトごとにAwake、次にOnEnableを呼び出しますが、順序は保証されていません。そのため、HealthのAwakeがHpを設定する前にバーのOnEnableが実行され、バーに0が表示される可能性があります。どのStartが実行されるときも、すべてのAwakeはすでに実行されています。

challenge icon

チャレンジ

簡単

銃が変更を通知し、HUDがそれを受け取るようにします。

  1. Gun.csで、using System;、public event Action<int, int> OnAmmoChanged、public event Action<bool> OnReloadingを追加し、コメントに書かれている箇所でイベントを発生させます。
  2. AmmoHud.csで、OnEnableで登録し、OnDisableで登録解除します。ammoTextにはAmmo: 4/6を表示し、reloadTextはリロード中のみ表示します。
  3. Startで、gun.Ammoとgun.Reloadingを一度表示します。

「プレイ」を押し、銃の弾を2回撃ち切ります。その後、「確認」を押します。

自分で試してみよう

using UnityEngine;
using TMPro;

public class AmmoHud : MonoBehaviour
{
    public Gun gun;
    public TMP_Text ammoText;
    public GameObject reloadText;
}

Unityのゲームアーキテクチャのすべてのレッスン

自分で練習してみよう: Unityプレイグラウンド