Unity中Coroutine引发异常刷怪问题求助
问题:Unity特殊技能触发后异常刷出大量敌人
- 原逻辑:敌人数为0时自动刷新新一波敌人,运行正常
- 新增特殊技能后:使用技能会一次性刷出约20波敌人,日志显示
enemyCount.Length先上升至某数值后莫名变为0,导致waveNumber持续增长到18左右
问题根源
- 协程重复启动:Player的
Update方法中,只要满足specialMove == true && 玩家Y坐标>0.8就会启动SpecialMoveDelay协程,导致同一时间运行多个协程,造成smashCam等状态混乱。 - Spawner无防重复刷波机制:
FixedUpdate中每帧检测敌人数,当敌人因特殊技能被批量销毁时,会连续多帧满足enemyCount.Length ==0,导致waveNumber持续递增,刷出大量敌人。 - Enemy边界判断逻辑错误:
CheckFallen方法中Z轴的边界判断重复,导致敌人超出负Z边界时不会被销毁,可能引发状态异常。
修复步骤
1. 修复Player的协程重复启动问题
添加isSpecialMoveRunning标志,防止同一时间启动多个协程:
public class PlayerController : MonoBehaviour { // ... 原有变量 ... private bool isSpecialMoveRunning = false; // 新增:协程运行状态标记 void Update() { // ... 原有移动逻辑 ... // 仅在协程未运行时启动 if (specialMove == true && gameObject.transform.position.y > 0.8 && !isSpecialMoveRunning) { StartCoroutine(SpecialMoveDelay()); } } IEnumerator SpecialMoveDelay() { isSpecialMoveRunning = true; // 标记协程启动 playerRb.constraints = RigidbodyConstraints.FreezePositionY; smashCam = true; yield return new WaitForSeconds(1); specialMove = false; smashCam = false; playerRb.constraints = RigidbodyConstraints.None; playerRb.AddForce(drop * dropForce, ForceMode.Impulse); // ... 击飞敌人逻辑 ... isSpecialMoveRunning = false; // 标记协程结束 } // ... 其他原有方法 ... }
2. 修复Spawner的重复刷波问题
添加isSpawning标志,确保每次仅刷一波敌人:
public class SpawnManagerScript : MonoBehaviour { // ... 原有变量 ... private bool isSpawning = false; // 新增:刷波状态标记 void FixedUpdate() { var enemyCount = FindObjectsByType<EnemyClass>(FindObjectsSortMode.None); Debug.Log("enemies = " + enemyCount.Length); // 仅在无敌人、非技能状态、未在刷波时触发 if (enemyCount.Length == 0 && playerController.smashCam == false && !isSpawning) { isSpawning = true; waveNumber++; Debug.Log("Wave Num = " + waveNumber); SpawnEnemyWave(waveNumber); Instantiate(powerUpPrefab, GenerateSpawnPoint(), powerUpPrefab.transform.rotation); if (waveNumber > 3) { Instantiate(healthPrefab, GenerateSpawnPoint(), powerUpPrefab.transform.rotation); } isSpawning = false; } } // ... 其他原有方法 ... }
3. 修复Enemy的边界判断逻辑
修正CheckFallen方法中的Z轴边界判断错误:
public class EnemyClass : MonoBehaviour { // ... 原有方法 ... public void CheckFallen() { if (transform.position.y < -10) { Destroy(gameObject); } // 修复Z轴负方向的边界判断 if (transform.position.x < -30 || transform.position.x > 30 || transform.position.z < -30 || transform.position.z > 30) { Destroy(gameObject); } } // ... 其他原有方法 ... }
额外优化建议
- 避免在
Update/FixedUpdate中频繁调用FindObjectsByType,可以维护一个敌人列表,在敌人生成/销毁时更新列表,提升性能。 - 将特殊技能的状态变量(如
specialMove、smashCam)改为私有,通过公共方法控制,避免外部误修改。
内容的提问来源于stack exchange,提问作者user23088743
相关产品推荐
相关产品推荐

