Unity协程嵌套循环异常:仅生成1个Chunk对象而非预期3个
问题排查:协程中仅生成1个Chunk实例而非预期3个
问题场景
需求是在DestroyingTree协程执行完毕后,以0.5秒间隔实例化3个chunk GameObject对象,但实际运行后只生成了1个实例。
原代码如下:
public class DestroyTree : MonoBehaviour { public Rigidbody chunk; public Transform TreeEnd; public GameObject leaves; void Start() { StartCoroutine(DestroyingTree()); } private IEnumerator DestroyingTree() { yield return new WaitForSeconds(3); Destroy(gameObject); leaves.GetComponent<ParticleSystem>().Play(); yield return SpawnChunks(); } private IEnumerator SpawnChunks() { for (int i = 0; i <= 2; i++) { yield return Spawner(); } } private IEnumerator Spawner() { Rigidbody chunkInstance; chunkInstance = Instantiate(chunk, TreeEnd.position, TreeEnd.rotation) as Rigidbody; chunkInstance.AddForce(TreeEnd.forward * 100f); yield return new WaitForSeconds(0.5f); } }
问题根源
核心问题出在DestroyingTree协程中的Destroy(gameObject);调用:
- 当前脚本挂载在树的GameObject上,调用
Destroy(gameObject)会立即销毁这个宿主对象 - 宿主对象被销毁后,挂载在它上面的所有脚本都会停止运行,后续的协程执行也会被终止
- 第一次执行
Spawner()时生成了第一个chunk,但还没来得及进入SpawnChunks的第二次循环,脚本就随宿主对象被销毁了,因此只生成1个实例
解决方案
方案1:调整销毁时机,先完成所有生成逻辑再销毁对象
把Destroy(gameObject);移到所有协程执行完成之后,确保脚本能完整跑完生成3个chunk的逻辑:
public class DestroyTree : MonoBehaviour { public Rigidbody chunk; public Transform TreeEnd; public GameObject leaves; void Start() { StartCoroutine(DestroyingTree()); } private IEnumerator DestroyingTree() { yield return new WaitForSeconds(3); leaves.GetComponent<ParticleSystem>().Play(); // 先执行完所有chunk生成逻辑,再销毁当前对象 yield return SpawnChunks(); Destroy(gameObject); } private IEnumerator SpawnChunks() { // 用i<3替代i<=2,逻辑更直观 for (int i = 0; i < 3; i++) { yield return Spawner(); } } private IEnumerator Spawner() { // 简化实例化代码,无需as转换(Instantiate返回Rigidbody类型) Rigidbody chunkInstance = Instantiate(chunk, TreeEnd.position, TreeEnd.rotation); chunkInstance.AddForce(TreeEnd.forward * 100f); yield return new WaitForSeconds(0.5f); } }
方案2:拆分生成逻辑到持久化对象(若需立即销毁树对象)
如果视觉上需要树立即消失,不能等到生成完chunk再销毁,可以:
- 创建一个场景持久化的空对象(比如命名为
ChunkSpawnerManager) - 将
SpawnChunks和Spawner方法移到这个管理器脚本中 - 在
DestroyingTree协程中调用管理器的生成方法,然后直接销毁树对象
示例管理器脚本:
public class ChunkSpawnerManager : MonoBehaviour { public static ChunkSpawnerManager Instance; public Rigidbody chunk; private void Awake() { Instance = this; // 确保对象在场景切换时不被销毁(按需选择) DontDestroyOnLoad(gameObject); } public IEnumerator SpawnChunks(Transform spawnTransform) { for (int i = 0; i < 3; i++) { yield return Spawner(spawnTransform); } } private IEnumerator Spawner(Transform spawnTransform) { Rigidbody chunkInstance = Instantiate(chunk, spawnTransform.position, spawnTransform.rotation); chunkInstance.AddForce(spawnTransform.forward * 100f); yield return new WaitForSeconds(0.5f); } }
修改后的DestroyTree脚本:
public class DestroyTree : MonoBehaviour { public Transform TreeEnd; public GameObject leaves; void Start() { StartCoroutine(DestroyingTree()); } private IEnumerator DestroyingTree() { yield return new WaitForSeconds(3); Destroy(gameObject); leaves.GetComponent<ParticleSystem>().Play(); // 调用管理器的生成方法 yield return ChunkSpawnerManager.Instance.SpawnChunks(TreeEnd); } }
内容的提问来源于stack exchange,提问作者Mohamed Khalil Boubaker
相关产品推荐
相关产品推荐

