イベントで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はすでに実行されています。
チャレンジ
簡単銃が変更を通知し、HUDがそれを受け取るようにします。
Gun.csで、using System;、public event Action<int, int> OnAmmoChanged、public event Action<bool> OnReloadingを追加し、コメントに書かれている箇所でイベントを発生させます。AmmoHud.csで、OnEnableで登録し、OnDisableで登録解除します。ammoTextにはAmmo: 4/6を表示し、reloadTextはリロード中のみ表示します。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プレイグラウンド