unity coroutine 无故停止

Posted

技术标签:

【中文标题】unity coroutine 无故停止【英文标题】:Unity coroutine stopping for no reason 【发布时间】:2021-11-25 04:53:22 【问题描述】:

我正在制作我的第一个 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; line 协程刚刚停止执行(我知道是因为我在 while 循环中插入了一个 Debug.Log 并且它被调用了,但是我在之后插入了一个并且它没有被调用)。

有什么建议吗?

【问题讨论】:

你可能在协程完成之前加载了一个新场景。 这怎么可能?我在 LoadScene() 的开头放置了一个 if 检查,以避免同时存在两个加载进程。 您是否尝试过生成新的 WaitForEndOfFrame() 而不是 null? 不。我应该把它放在两个产量中的哪一个?为什么? 【参考方案1】:

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

【讨论】:

以上是关于unity coroutine 无故停止的主要内容,如果未能解决你的问题,请参考以下文章

Unity C# - 在完成之前停止执行IJobParallelFor

Unity3D中的Coroutine具体解释

Unity3D/C#Unity3D中的Coroutine详解

Unity协程(Coroutine)原理深入剖析再续

unity——Coroutine

C#中的yield return与Unity中的Coroutine(协程)(下)