我已经在我的Unity 2D项目的主要Gameplay.cs脚本中研究了这部分代码了很长一段时间,无论我改变它并改变它的方式,它要么导致Unity锁定在播放或经过一些调整之后,它将立即从Wave 0转到Wave 9.这是我最初的尝试,这会导致Unity在Play上冻结。我不明白为什么会发生这种情况,并希望了解我的逻辑出错的地方。
我正在努力实现以下目标:
private float startWait = 3f; //Amount of time to wait before first wave
private float waveWait = 2f; //Amount of time to wait between spawning each wave
private float spawnWait = 0.5f; //Amount of time to wait between spawning each enemy
private float startTimer = 0f; //Keep track of time that has elapsed since game launch
private float waveTimer = 0f; //Keep track of time that has elapsed since last wave
private float spawnTimer = 0f; //Keep track of time that has elapsed since last spawn
private List<GameObject> zombies = new List<GameObject>();
[SerializeField]
private Transform spawnPoints; //The parent object containing all of the spawn point objects
void Start()
{
deathUI.SetActive(false);
//Set the default number of zombies to spawn per wave
zombieCount = 5;
PopulateZombies();
}
void Update()
{
startTimer += Time.deltaTime;
if (startTimer >= startWait)
{
waveTimer += Time.deltaTime;
spawnTimer += Time.deltaTime;
SpawnWaves();
}
//When the player dies "pause" the game and bring up the Death screen
if (Player.isDead == true)
{
Time.timeScale = 0;
deathUI.SetActive(true);
}
}
void SpawnWaves()
{
while (!Player.isDead && ScoreCntl.wave < 9)
{
if (waveTimer >= waveWait)
{
IncrementWave();
for (int i = 0; i < zombieCount; i++)
{
if (spawnTimer >= spawnWait)
{
Vector3 spawnPosition = spawnPoints.GetChild(Random.Range(0, spawnPoints.childCount)).position;
Quaternion spawnRotation = Quaternion.identity;
GameObject created = Instantiate(zombies[0], spawnPosition, spawnRotation);
TransformCreated(created);
spawnTimer = 0f;
}
}
waveTimer = 0f;
}
}
}
我是初学者并且理解我的代码可能不遵循最佳实践。我还有一个使用Coroutine和产量回报的工作敌人产卵者,但我想让这个版本的我的敌人产卵。
答案 0 :(得分:2)
我对Unity没有任何经验,但对于XNA,我假设他们的主要游戏处理与使用Update()和Draw()函数相似。
Update()函数通常每秒调用几次,在你的代码中,SpawnWaves()应该在每次Update调用后执行一次startTimer&gt; = startWait。
让我们看一下SpawnWaves()
void SpawnWaves()
{
while (!Player.isDead && ScoreCntl.wave < 9)
{
if (waveTimer >= waveWait)
{
IncrementWave();
for (int i = 0; i < zombieCount; i++)
{
if (spawnTimer >= spawnWait)
{
[..]
spawnTimer = 0f;
}
}
waveTimer = 0f;
}
}
}
这个while循环是个问题,因为它是游戏循环中的一种游戏循环。如果玩家已经死亡或者你的波数超过9,它将只会退出。
在调用SpawnWaves()之后,有两种可能性,取决于Time.deltaTime,它在程序启动后或多或少是随机的,waveTimer可以大于或小于waveWait。
案例:waveTimer&gt; = waveWait
内部的所有代码都将立即执行。 因此,如果它可以使用IncrementWave(),它将在毫秒内完成九次。然后,虽然是假的,但内部的代码再也没有执行过。
案例:waveTimer&lt; waveWait
在这种情况下,永远不会调用IncrementWave(),你的游戏可以在这个while循环中旋转无数。
所以你要做的就是用if语句替换这个while循环,以允许程序继续。
If(!Player.isDead && ScoreCntl.wave < 9)
从那时起,您的计数器递增将在Update()上多次调用。
waveTimer += Time.deltaTime;
spawnTimer += Time.deltaTime;
随着时间的推移,波浪变换和产卵的条件会变得真实。
if (waveTimer >= waveWait),
if (spawnTimer >= spawnWait)
我希望这可以指导您解决问题。
<强>更新强>
对于这种行为,分离IncrementWave和生成条件是个好主意。为此,您需要一个额外的bool变量,在此示例中称为haveToSpawn。
if (waveTimer >= waveWait)
{
IncrementWave();
waveTimer = 0f;
haveToSpawn = true; //new variable
}
if (haveToSpawn && spawnTimer >= spawnWait)
{
for (int i = 0; i < zombieCount; i++)
{
[..] //spawn each zonbie
}
spawnTimer = 0f; //reset spawn delay
haveToSpawn = false; //disallow spawing
}
答案 1 :(得分:1)
使用协程来调用spawn wave方法:
private float startWait = 3f; //Amount of time to wait before first wave
private float waveWait = 2f; //Amount of time to wait between spawning each wave
private float spawnWait = 0.5f; //Amount of time to wait between spawning each enemy
private float startTimer = 0f; //Keep track of time that has elapsed since game launch
private float waveTimer = 0f; //Keep track of time that has elapsed since last wave
private float spawnTimer = 0f; //Keep track of time that has elapsed since last spawn
private List<GameObject> zombies = new List<GameObject>();
[SerializeField]
private Transform spawnPoints; //The parent object containing all of the spawn point objects
void Start()
{
deathUI.SetActive(false);
//Set the default number of zombies to spawn per wave
zombieCount = 5;
PopulateZombies();
StartCoroutine(SpawnWaves());
}
void Update()
{
startTimer += Time.deltaTime;
if (startTimer >= startWait)
{
waveTimer += Time.deltaTime;
spawnTimer += Time.deltaTime;
}
//When the player dies "pause" the game and bring up the Death screen
if (Player.isDead == true)
{
Time.timeScale = 0;
deathUI.SetActive(true);
}
}
IEnumerator SpawnWaves()
{
//wait 3 seconds
yield return new WaitForSeconds(startWait);
//then:
while (!Player.isDead && ScoreCntl.wave < 9)
{
if (waveTimer >= waveWait)
{
IncrementWave();
for (int i = 0; i < zombieCount; i++)
{
if (spawnTimer >= spawnWait)
{
Vector3 spawnPosition = spawnPoints.GetChild(Random.Range(0, spawnPoints.childCount)).position;
Quaternion spawnRotation = Quaternion.identity;
GameObject created = Instantiate(zombies[0], spawnPosition, spawnRotation);
TransformCreated(created);
spawnTimer = 0f;
}
}
waveTimer = 0f;
}
//wait until the end of frame
yield return null;
}
}
要更好地理解统一协程如何工作:
协程是一种返回类型为IEnumerator的方法,其行为是异步执行的代码块集合。 yield指令将代码块分开,并指定在下一个代码块开始执行之前等待的时间量。
有几种类型的良率指令:
你可以想到