イベントでUIを動かす
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 13/50。
イベントを使うと、ゲーム側は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の組み合わせによって、アクティブな間だけイベントを購読します。イベントは両方の数値を渡すので、ShowはHealthからほかに何も受け取る必要がありません。GameOverScreenはパネルを表示するためにOnDiedを購読し、ダメージ音はOnChangedを購読します。それぞれ別のスクリプトで処理され、Healthはどちらのためにも変更する必要がありません。Hp { get; private set; }を使えば、HUDは体力を読み取れますが、変更はできません。
イベントは変化を通知するため、最初に攻撃を受けるまではバーには何も通知されません。現在の体力はStartで一度描画します。OnEnableでは描画しません。UnityはオブジェクトごとにAwakeを呼び、その後OnEnableを呼びますが、その順序は保証されていません。そのため、HealthのAwakeでHpが設定される前に、バーのOnEnableが実行されてしまい、バーには0が表示される可能性があります。Startが実行される頃には、すべてのAwakeが実行済みです。
チャレンジ
簡単射撃場です。Space キーで銃(Gun.cs)を撃ちます。銃には maxAmmo(6 発)があり、最後の 1 発を撃つと reloadTime(1.5 秒)のリロードが始まり、弾が補充されます。HUD にはまだ何も表示されません。銃に変更を通知させ、HUD がその通知を受け取るようにしましょう。銃に HUD 用のフィールドは追加しません。
Gun.csに、次の 2 つの public イベントを追加します。弾数とmaxAmmo(どちらも int)を渡すOnAmmoChangedと、bool を渡すOnReloadingです。リロード開始時は true、終了時は false を渡します。コメントの指示に従ってイベントを発行してください。- HUD 上の
AmmoHud.csで、HUD がアクティブな間、両方のイベントを受け取ります。ammoTextには弾数をAmmo: 4/6と表示し、reloadText(Reloading...というテキストを含むオブジェクト)はリロード中だけ表示します。 - 最初の発砲より前から、HUD に正しい情報を表示します。
Ammo: 6/6と表示し、リロードのテキストは表示しません。銃のAmmoプロパティとReloadingプロパティから、現在の値を取得できます。 - HUD が破棄されても、銃はエラーを起こさずに撃ち続けられます。
Play を押し、銃の弾を 2 回撃ち切ってから、Check を押してください。
自分で試してみよう
using UnityEngine;
using TMPro;
public class AmmoHud : MonoBehaviour
{
public Gun gun;
public TMP_Text ammoText;
public GameObject reloadText;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。