首页 > 解决方案 > unity coroutine 无故停止

问题描述

我正在制作我的第一个 2D 自上而下的射击游戏。我正在处理游戏的加载部分。我有这个功能加载屏幕功能(我的 GameManager 类的方法)我做了。我尝试在主标题场景和第一关之间切换几次来测试它。加载第一级后,然后是标题屏幕,当我尝试再次加载第一级时,加载屏幕卡住了。整个事情都在一个协程上工作,经过一些调试,我发现问题是这个协程由于某种原因在代码的某个部分停止执行。

public static bool isLoadingScene { get; private set; } = false;

public void LoadScene(int sceneIndex)
{
    // If another scene is already loading, abort
    if (isLoadingScene)
    {
        Debug.LogWarning($"Attempting to load scene {sceneIndex} while another scene is already loading, aborting");
        return;
    }

    isLoadingScene = true;

    var sceneLoader = FindObjectOfType<SceneLoader>().gameObject;

    if (sceneLoader != null)
    {
        // Make the loading screen appear
        var animator = sceneLoader.GetComponent<Animator>();
        animator.SetTrigger("appear");

        // Make sure the SceneLoader object is maintained until the next scene
        // in order to not make the animation stop
        DontDestroyOnLoad(sceneLoader);
    }
    else // If a SceneLoader is not found in the current scene, throw an error
    {
        Debug.LogError($"SceneLoader could not be found in {SceneManager.GetActiveScene().name}");
    }

    // Unload active scene and load new one
    StartCoroutine(LoadScene_(sceneIndex, sceneLoader));
}

IEnumerator LoadScene_(int sceneIndex, GameObject sceneLoader)
{
    float t = Time.time;

    // 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;

    // Unload old scene
    AsyncOperation unload = SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());

    // Wait until it's finished unloading
    while (!unload.isDone) yield return null;
    // --- THE COROUTINE STOPS HERE DURING THE 3RD LOADING --- //

    // 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;
}

仅在第 3 次加载期间,就在 while (!unload.isDone) yield return null 之后;行协程刚刚停止执行(我知道是因为我在 while 循环中插入了一个 Debug.Log 并被调用,但我在之后插入了一个但没有被调用)。

有什么建议么?

标签: c#unity3dcoroutine

解决方案


我自己解决了这个问题。GameManager 本身被编程为单例,因为在两个场景中都有一个 GameManager 把事情搞砸了。必须将 GameManager 移动到附加加载的单独场景。


推荐阅读