You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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再销毁,可以:

  1. 创建一个场景持久化的空对象(比如命名为ChunkSpawnerManager)
  2. 将SpawnChunks和Spawner方法移到这个管理器脚本中
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:41:01