将波次作为数据
本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 27 课,共 64 课。
一个关卡的波次是一个列表:先出现 3 个杂兵,然后是 2 个蛮兵,最后是一个首领。如果把这些内容写在生成器的代码里,每个关卡都需要自己的代码。如果把它们写成数据,列表就可以放进资源中,每个关卡对应一个资源,生成器脚本读取传给它的资源即可。每个条目都是一个 [System.Serializable] 类,因此资源的 Inspector 会显示这个列表:
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Wave
{
public GameObject enemy;
public int count = 1;
public float spacing = 1f;
}
[CreateAssetMenu(menuName = "Game/Wave Set")]
public class WaveSet : ScriptableObject
{
public List<Wave> waves;
public float restBetweenWaves = 3f;
}所有内容都放在一个文件 WaveSet.cs 中:ScriptableObject 需要单独放在一个与它同名的文件里,而普通的 Wave 类可以和它放在一起。选中一个 WaveSet 资源后,Inspector 会显示 Waves,其中包含 Size 和 Element 0、Element 1 等行,每行都有 Enemy、Count 和 Spacing;点击 + 按钮即可添加一个波次。生成器会在协程中遍历列表:
public class WaveSpawner : MonoBehaviour
{
public WaveSet waveSet;
void Start()
{
StartCoroutine(SendWaves());
}
IEnumerator SendWaves()
{
foreach (Wave wave in waveSet.waves)
{
for (int i = 0; i < wave.count; i++)
{
Instantiate(wave.enemy, transform.position, Quaternion.identity);
yield return new WaitForSeconds(wave.spacing);
}
yield return new WaitForSeconds(waveSet.restBetweenWaves);
}
Debug.Log("Last wave sent");
}
}Level1 中有 3 个杂兵,每隔 0.5 秒出现一个,然后是 2 个蛮兵。杂兵分别在第 0 秒、0.5 秒和 1 秒出现,最后一个杂兵之后会等待间隔时间,再等待 3 秒,随后第一个蛮兵在第 4.5 秒出现。Level 2 的生成器使用包含更难波次的 Level2 资源,脚本则保持不变。
挑战
中等把 Dropper 的节奏变成歌曲资源。
- 在
DropPattern.cs中,编写一个带有[System.Serializable]的类Drop,其中包含公共属性int lane和float delay。 - 在它下面,编写
DropPattern : ScriptableObject,添加[CreateAssetMenu],并包含公共属性GameObject blockPrefab、float laneWidth和List<Drop> drops。 - 在
Dropper中,使用public DropPattern pattern;:对每个掉落项,等待drop.delay,然后让方块沿 x 轴移动drop.lane * pattern.laneWidth后掉落。
按下 Play:四个方块会落下。然后点击 Check。
亲手试试
using System.Collections.Generic;
using UnityEngine;
// Drop(一个方块:它所在的轨道和出现前的等待时间)和 DropPattern(资源文件)放在这里
Unity 游戏架构中的所有课
自己练习: Unity 在线编辑器