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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:36:04