Unity协程执行yield return new WaitForSeconds(.01f)后后续代码不运行如何解决
问题根因
调用SceneManager.LoadScene加载新场景时,Unity默认会销毁当前场景中所有的GameObject,启动Exiting协程的宿主对象也会被一同销毁,协程会随对象销毁而中断,因此yield return之后的逻辑不会执行。
你设置的0.01秒固定等待也存在风险:不同设备的场景加载耗时不同,固定等待时间无法保证场景加载完成后再执行传送逻辑,容易出现空引用、传送失效的问题。
可行解决方案
方案1:标记协程宿主对象为跨场景不销毁
在加载场景前调用DontDestroyOnLoad,让挂载当前脚本的对象不会随场景加载被销毁,保证协程可以执行完全部逻辑,同时用异步加载代替固定时间等待,适配不同设备性能。
修正后的代码如下:
private IEnumerator Exiting() { // 标记当前对象为跨场景留存,避免被销毁 DontDestroyOnLoad(gameObject); // 异步加载场景,等待加载完全完成后再执行后续逻辑 AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("Opening Stage"); yield return asyncLoad; Debug.Log("Scene loaded, lastPos: " + myLocation.getLastPos()); Debug.Log("After Coroutine"); myLocation.ReturnToLastPos(); // 如果该对象后续不需要留存,执行完逻辑后自行销毁即可 Destroy(gameObject); }
方案2:使用场景加载完成事件回调
也可以通过监听Unity的场景加载完成事件执行传送逻辑,不需要依赖当前协程的生命周期:
private void StartExiting() { // 绑定场景加载完成事件 SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.LoadScene("Opening Stage"); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { // 校验加载的是目标场景再执行逻辑 if (scene.name == "Opening Stage") { // 用完后解绑事件避免重复触发 SceneManager.sceneLoaded -= OnSceneLoaded; Debug.Log("Scene loaded, lastPos: " + myLocation.getLastPos()); Debug.Log("After Coroutine"); myLocation.ReturnToLastPos(); } }
注意事项
如果myLocation是当前场景挂载的组件,也需要对其所在的GameObject执行DontDestroyOnLoad标记,否则新场景加载后该对象会被销毁,调用getLastPos、ReturnToLastPos时会触发空引用报错。
内容的提问来源于stack exchange,提问作者memeaste
相关产品推荐
相关产品推荐

