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

Unity中yield return后代码不执行,GameObject无法重新激活求助

问题解答

一、yield return后代码无法执行的原因分析

第一种代码的问题

你写的第一个协程里加了个完全多余的while循环:

while (!target.gameObject.active)
{
    yield return new WaitForSeconds(seconds);
}

当你执行target.SetActive(false)后,!target.active的结果永远是true,这个循环会无限重复等待,永远跳不出去,自然到不了后面的target.SetActive(true)。

第二种代码的问题

第二种代码的逻辑本身没问题,但协程的承载对象被停用了。如果你的PickupController脚本是挂在要被停用的target对象上,那么当target.SetActive(false)执行后,这个对象会进入非激活状态,Unity会直接暂停该对象上所有协程的运行,yield return之后的代码就永远没机会执行了。

二、解决GameObject停用后无法重新激活的方案

核心思路是:让协程在一个永远不会被停用的对象上运行,避免对象停用导致协程中断。

方案1:用全局协程管理器

创建一个专门的CoroutineManager脚本,挂在场景中永远保持激活的对象(比如GameManager)上:

public class CoroutineManager : MonoBehaviour
{
    public static CoroutineManager Instance;

    private void Awake()
    {
        // 确保全局唯一且不随场景销毁
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public IEnumerator Reactivate(float seconds, GameObject target)
    {
        target.SetActive(false);
        yield return new WaitForSeconds(seconds);
        target.SetActive(true);
    }
}

调用的时候直接通过单例启动协程:

// 在任意需要的地方调用
CoroutineManager.Instance.StartCoroutine(CoroutineManager.Instance.Reactivate(3f, yourTargetGameObject));

方案2:用Invoke替代协程

如果不想用协程,也可以用Invoke实现同样的效果,同样要确保调用Invoke的对象不会被停用:

// 挂在永远激活的对象上
private GameObject targetCache;

public void ScheduleReactivate(float seconds, GameObject target)
{
    targetCache = target;
    target.SetActive(false);
    Invoke(nameof(ActivateTarget), seconds);
}

private void ActivateTarget()
{
    targetCache.SetActive(true);
}

额外提醒

不要在要被停用的对象上启动协程或者调用Invoke,只要对象一停用,这些延迟执行的逻辑都会被Unity暂停,永远无法完成。

内容的提问来源于stack exchange,提问作者Hale Jan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:50:28