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

Unity Button onClick监听器代码执行顺序异常问题

问题根因

这不是代码执行顺序错乱,是Unity控制台日志的刷新机制导致的显示错觉:

  • 代码里的Debug.Log("Loading level ... ")确实在SceneManager.LoadSceneAsync之前执行,但Unity默认不会把日志立刻输出到控制台,会把当前帧内所有日志攒到帧末尾统一渲染输出。
  • LoadSceneAsync调用后会立刻启动场景加载流程,当新场景加载到可切换状态时,Unity会打断当前帧的剩余执行流程直接完成场景切换,攒着没输出的日志就会被延后到新场景加载完成后才显示,看起来就像先加载场景再打日志。
  • 你调换两行代码顺序结果完全一致,也能佐证这一点:只要日志还没来得及刷出就触发了场景切换,不管日志写在加载调用前还是后,都会出现这个显示问题,和实际代码执行顺序无关。

你可以做个简单验证:在日志和加载调用之间加一行System.Threading.Thread.Sleep(2000);,运行时会先等2秒,再触发场景加载,等场景加载完才会看到日志,完全能证明代码执行顺序本身是对的。

可用解决方案

根据项目需求选一种就行:

  • 方案1(最稳妥,无平台限制):把场景加载逻辑延后一帧执行,给日志留出足够的输出时间,用async/await实现最简洁:
void Awake()
{
    button = GetComponent<Button>();
    button.onClick.RemoveAllListeners();
    button.onClick.AddListener(async () =>
    {
        Debug.Log("Loading level ... ");
        // 等待当前帧执行结束、日志正常输出后再启动加载
        await Task.Yield();
        SceneManager.LoadSceneAsync(levelName);
    });
}

如果项目不方便用Task,用协程实现效果完全一致:

void Awake()
{
    button = GetComponent<Button>();
    button.onClick.RemoveAllListeners();
    button.onClick.AddListener(() =>
    {
        Debug.Log("Loading level ... ");
        StartCoroutine(LoadLevelDelay());
    });
}

IEnumerator LoadLevelDelay()
{
    yield return new WaitForEndOfFrame();
    SceneManager.LoadSceneAsync(levelName);
}
  • 方案2(最轻量,仅Editor/开发包生效):手动强制刷新日志输出流,不需要改执行逻辑:
button.onClick.AddListener(() =>
{
    Debug.Log("Loading level ... ");
    // 强制立刻把日志刷到控制台
    System.Console.Out.Flush();
    SceneManager.LoadSceneAsync(levelName);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 05:00:49