Unity Enemy Spawner While循环无法生成指定数量敌人
敌人生成脚本异常问题
我尝试在测试区域内自动生成指定数量的敌人,逻辑为当前敌人数量小于期望数量时,激活循环生成。但脚本存在问题:初始运行无法实例化正确数量的敌人,游戏中敌人被击杀后虽会补充,但始终达不到期望数量。
不同期望数量对应的实际生成结果:
| 期望敌人数量(enemiesDesired) | 实际生成数量 |
|---|---|
| 1 | 0 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 3 |
| 8 | 3 |
| 9 | 3 |
| 10 | 4 |
| 11 | 4 |
| 12 | 5 |
| 13 | 5 |
| 14 | 6 |
初始代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnEnemies : MonoBehaviour { //Enemies array public GameObject[] Enemies; public int enemiesInArray; //Spawn enemy within these positions on the map private int xPos; private int zPos; private int yPos; private int randomEnemy; public static int enemiesCurrentCount; //Amount of enemies in game currently public int enemiesDesired; //Amount of enemies desired in game at the same time public bool keepSpawning; //Wait timers public float startWaitSeconds; public float spawnWaitSeconds; void Start() { enemiesCurrentCount = 0; keepSpawning = true; } void Update() { //Check if new enemies should be spawned if (enemiesCurrentCount <= enemiesDesired) { keepSpawning = true; StartCoroutine(RandomSpawnEnemies()); } else { keepSpawning = false; } } //Spawn Enemies IEnumerator RandomSpawnEnemies() { yield return new WaitForSeconds(startWaitSeconds); while (keepSpawning) { randomEnemy = Random.Range(0, enemiesInArray); xPos = Random.Range(-10, 8); zPos = Random.Range(17, 30); Instantiate(Enemies[randomEnemy], new Vector3(xPos, yPos, zPos), Quaternion.identity); enemiesCurrentCount += 1; yield return new WaitForSeconds(spawnWaitSeconds); } } }
测试用修改代码
为定位问题,我将生成逻辑移至Start阶段,但设置enemiesDesired=5时仍仅生成2只敌人:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnEnemies : MonoBehaviour { //Enemies array public GameObject[] Enemies; public int enemiesInArray; //Spawn enemy within these positions on the map private int xPos; private int zPos; private int yPos; private int randomEnemy; public int enemiesCurrentCount = 0; //Amount of enemies in game currently public int enemiesDesired = 5; //Amount of enemies desired in game at the same time //Wait timers public float spawnWaitSeconds; void Start() { StartCoroutine(SpawnRandomEnemies()); } void Update() { } //Spawn Enemies IEnumerator SpawnRandomEnemies() { while (enemiesCurrentCount < enemiesDesired) { randomEnemy = Random.Range(0, enemiesInArray); xPos = Random.Range(-10, 8); zPos = Random.Range(17, 30); Instantiate(Enemies[randomEnemy], new Vector3(xPos, 1, zPos), Quaternion.identity); enemiesCurrentCount += 1; yield return new WaitForSeconds(0.1f); } } }
问题根源与修复方案
核心问题
- 初始代码重复启动协程:
Update每帧检测到需要生成就启动一次协程,导致多个协程并行运行,同时修改enemiesCurrentCount,计数逻辑完全混乱,最终生成数量失控。 - 测试代码的潜在漏洞:
enemiesInArray为手动赋值,若与Enemies数组实际长度不符,比如设为0或小于数组长度,Random.Range(0, enemiesInArray)会触发错误,协程直接中断,停止生成。- 生成的敌人可能因碰撞或自身脚本被立刻销毁,导致场景中看不到敌人,但计数已增加。
修复代码
修正后的持续生成脚本
解决重复启动协程的问题,同时增加数组有效性检查:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnEnemies : MonoBehaviour { public GameObject[] Enemies; public int enemiesDesired; public static int enemiesCurrentCount; public float startWaitSeconds; public float spawnWaitSeconds; private bool _isSpawning; // 标记协程是否在运行,避免重复启动 void Start() { enemiesCurrentCount = 0; _isSpawning = false; } void Update() { // 仅在需要生成且无协程运行时启动 if (enemiesCurrentCount < enemiesDesired && !_isSpawning) { StartCoroutine(SpawnEnemiesCoroutine()); } } IEnumerator SpawnEnemiesCoroutine() { _isSpawning = true; yield return new WaitForSeconds(startWaitSeconds); while (enemiesCurrentCount < enemiesDesired) { // 先检查数组是否有效 if (Enemies.Length == 0) { Debug.LogError("敌人预制体数组未赋值!"); break; } int randomIndex = Random.Range(0, Enemies.Length); Vector3 spawnPos = new Vector3(Random.Range(-10, 8), 0, Random.Range(17, 30)); Instantiate(Enemies[randomIndex], spawnPos, Quaternion.identity); enemiesCurrentCount++; yield return new WaitForSeconds(spawnWaitSeconds); } _isSpawning = false; } }
修正后的测试脚本
移除手动设置的enemiesInArray,直接使用数组长度,添加日志排查生成情况:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnEnemies : MonoBehaviour { public GameObject[] Enemies; public int enemiesCurrentCount = 0; public int enemiesDesired = 5; void Start() { StartCoroutine(SpawnTestCoroutine()); } IEnumerator SpawnTestCoroutine() { if (Enemies.Length == 0) { Debug.LogError("敌人预制体数组为空!"); yield break; } while (enemiesCurrentCount < enemiesDesired) { int randomIndex = Random.Range(0, Enemies.Length); Vector3 spawnPos = new Vector3(Random.Range(-10, 8), 1, Random.Range(17, 30)); GameObject enemy = Instantiate(Enemies[randomIndex], spawnPos, Quaternion.identity); Debug.Log($"生成第{enemiesCurrentCount + 1}只敌人,当前计数:{enemiesCurrentCount + 1}"); enemiesCurrentCount++; // 可选:检查敌人是否被立刻销毁 if (!enemy) { Debug.LogWarning("生成的敌人已被销毁"); enemiesCurrentCount--; } yield return new WaitForSeconds(0.1f); } Debug.Log($"生成完成,最终计数:{enemiesCurrentCount}"); } }
额外排查点
- 检查敌人预制体:是否有脚本在
Awake/Start中自动销毁敌人? - 检查生成位置:是否生成在碰撞体内部(比如地面以下),导致敌人被挤开或销毁?可将y轴数值调高测试。
- 确认计数逻辑:敌人被击杀时是否正确执行
enemiesCurrentCount--,且没有其他代码错误修改该数值。
内容的提问来源于stack exchange,提问作者WolfPG
相关产品推荐
相关产品推荐

