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

Unity协程yield执行前为何运行后续语句?暂停逻辑异常

问题原因

核心问题是对Unity协程的执行逻辑存在误解:

  • 调用StartCoroutine()启动协程时,协程只会立刻执行到第一次yield return语句的位置,随后就会把控制权交回给调用方,不会阻塞调用方后续的主线程代码执行。
  • 你当前代码的实际执行顺序为:
    • 执行DisplayTileFronts()
    • 启动PauseGame协程:协程同步执行到Time.timeScale = 0f、计算等待结束时间、进入while循环,碰到yield return 0后暂停本次协程执行,控制权返回Start()方法
    • 立刻执行DisplayTileBacks(),完全没有等待3秒的暂停结束
    • 后续每帧引擎会恢复协程执行判断时间,等满3秒后才会把Time.timeScale设回1,完全不符合预期的暂停结束后再显示牌背的逻辑。
修复方案

两种常用改法都可以实现预期效果,可根据代码结构选择:

方案1:将Start改为协程,等待PauseGame执行完成后再执行后续逻辑

Unity支持将生命周期函数Start的返回值设为IEnumerator,直接在Start里等待协程执行完毕即可,逻辑最直观:

IEnumerator Start()
{
    // ... 保留原有其他逻辑
    DisplayTileFronts();
    // 等待PauseGame协程完整执行完(即3秒暂停结束)再往下走
    yield return StartCoroutine(PauseGame(3f));
    DisplayTileBacks();
}

public IEnumerator PauseGame(float waitTime)
{
    Time.timeScale = 0f;
    float waitEndTime = Time.realtimeSinceStartup + waitTime;
    while (Time.realtimeSinceStartup < waitEndTime)
    {
        yield return 0;
    }
    Time.timeScale = 1f;
}

方案2:将暂停后执行的逻辑移入PauseGame协程末尾

不需要修改Start的返回值,直接把暂停结束后要跑的逻辑放到协程等待完成的位置即可:

void Start()
{
    // ... 保留原有其他逻辑
    DisplayTileFronts();
    StartCoroutine(PauseGame(3f));
}

public IEnumerator PauseGame(float waitTime)
{
    Time.timeScale = 0f;
    float waitEndTime = Time.realtimeSinceStartup + waitTime;
    while (Time.realtimeSinceStartup < waitEndTime)
    {
        yield return 0;
    }
    Time.timeScale = 1f;
    // 3秒暂停结束后再执行显示牌背逻辑
    DisplayTileBacks();
}

注:当前用Time.realtimeSinceStartup做等待判断的写法是正确的,Time.timeScale = 0时所有受时间缩放影响的等待方法(比如WaitForSeconds)会完全失效,用真实时间计时才能正常等待。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:27:37