アリーナをクリアする
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 55/64。
staticが付いたイベントは、1つのオブジェクトではなくクラスに属します。今後存在する敵の数にかかわらず、Enemy.Diedは1つだけなので、スポナーは敵がまだ1体も存在しないうちにEnemy.Died += OnEnemyDied;で購読でき、各敵は自身を引数としてイベントを発生させます。通常のC#で同じ考え方を示すと、次のようになります。
public class Coin
{
public static event Action<Coin> Picked;
public void Pick()
{
Picked?.Invoke(this);
}
}
public class Purse
{
private int coins;
public Purse()
{
Coin.Picked += OnPicked; // まだ Coin は必要ない
}
void OnPicked(Coin coin)
{
coins++;
}
}インスタンスイベントにはhero.Diedのようにオブジェクト経由でアクセスし、静的イベントにはCoin.Pickedのようにクラス名経由でアクセスします。静的イベントはすべてのオブジェクトが破棄された後も存続するため、OnDisableで購読を解除してください。そうしないと、破棄されたスポナーがリストに残ったままになります。
チャレンジ
中級アリーナが片付くまで、各ウェーブを待機させましょう。
Enemyにpublic static event Action<Enemy> Died;を追加し、Destroy(gameObject);の直前にDied?.Invoke(this);を呼び出します。WaveSpawnerでaliveを数えます。スポーンごとに 1 を加算し、OnEnableでEnemy.Diedに登録し、OnDisableで登録を解除するメソッド内で 1 を減算します。- ウェーブのスポーン後、
alive > 0の間は待機します。
「プレイ」を押してウェーブ 1 を倒すと、2 秒後にウェーブ 2 が始まります。その後、「確認」を押します。
自分で試してみよう
using System.Collections;
using UnityEngine;
public class WaveSpawner : MonoBehaviour
{
[SerializeField] private WaveSet waveSet;
[SerializeField] private Transform[] spawnPoints;
public int Wave { get; private set; }
void Start()
{
StartCoroutine(RunWaves());
}
IEnumerator RunWaves()
{
while (true)
{
foreach (Wave wave in waveSet.waves)
{
Wave++;
Debug.Log("Wave " + Wave);
for (int i = 0; i < wave.count; i++)
{
Transform point = spawnPoints[i % spawnPoints.Length];
Instantiate(wave.enemy, point.position, Quaternion.identity);
yield return new WaitForSeconds(wave.spacing);
}
yield return new WaitForSeconds(waveSet.restBetweenWaves);
}
}
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド