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
相关产品推荐
相关产品推荐

