清空竞技场
本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 55 课,共 64 课。
标记为 static 的事件属于类,而不是某个对象。无论有多少敌人,Enemy.Died 都只有一个,因此生成器可以在任何敌人出现之前订阅该事件: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 在线编辑器