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

