Unity反复切换场景时协程无故停止 加载界面卡住问题求助
场景加载协程中途停止问题排查与解决思路
核心排查点
- 验证GameManager生命周期
你启动协程的GameManager实例如果挂载在每次需要卸载的普通场景,且没有设置DontDestroyOnLoad,执行UnloadSceneAsync时GameManager会随旧场景一起被销毁,它启动的所有协程会立即终止,这是协程中途无报错停止的最常见原因。
如果已经设置了DontDestroyOnLoad,需要检查每次新加载的场景中是否也存在GameManager实例,重复的实例会触发逻辑冲突,甚至销毁正在运行协程的原有实例。 - 校验卸载场景的引用正确性
你的代码存在明显逻辑错误:load.allowSceneActivation = true执行后新场景会被激活,此时调用SceneManager.GetActiveScene()拿到的是刚加载的新场景,你实际执行卸载的是新场景而非旧场景。前两次加载未触发问题只是状态延迟的偶发表现,第三次加载时状态混乱累积最终导致协程终止。 - 确认全局状态正确性
加日志打印isLoadingScene的实际值,排查前两次加载是否因为异常导致状态没有正常重置,引发第三次加载的逻辑冲突。
修复方案
1. 提前保存旧场景引用,修正卸载逻辑
IEnumerator LoadScene_(int sceneIndex, GameObject sceneLoader) { float t = Time.time; // 加载新场景前提前保存要卸载的旧场景引用 Scene oldScene = SceneManager.GetActiveScene(); // Start loading the new scene, but don't activate it yet AsyncOperation load = SceneManager.LoadSceneAsync(sceneIndex, LoadSceneMode.Additive); load.allowSceneActivation = false; // Wait until the loading is finished, but also give the loading screen enough time to appear while (load.progress < 0.9f || Time.time <= (t + LoadingScreen_appearTime)) { yield return null; } // Activate loaded scene load.allowSceneActivation = true; // 等待新场景完全激活 yield return new WaitUntil(() => load.isDone); // 卸载之前保存的旧场景,而非当前激活的新场景 AsyncOperation unload = SceneManager.UnloadSceneAsync(oldScene); // Wait until it's finished unloading while (!unload.isDone) yield return null; // Make the loading screen disappear sceneLoader.GetComponent<Animator>().SetTrigger("disappear"); // Wait until the disappearing animation is over, then destroy the SceneLoader object which I set to DontDestroyOnLoad before yield return new WaitForSeconds(LoadingScreen_disappearTime); Destroy(sceneLoader); isLoadingScene = false; }
2. 给GameManager添加全局单例逻辑
保证全局唯一且不会被场景卸载销毁,从根源避免协程载体被销毁的问题:
public class GameManager : MonoBehaviour { public static GameManager Instance { get; private set; } public static bool isLoadingScene { get; private set; } = false; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); } // 其余原有逻辑保持不变 }
内容的提问来源于stack exchange,提问作者giorgio_developer
相关产品推荐
相关产品推荐

