Home > Blockchain >  Unity coroutine stopping for no reason
Unity coroutine stopping for no reason

Time:10-09

I'm making my first 2D topdown shooter game. I'm working on the loading part of the game. I have this functioning loading screen function (a method of my GameManager class) I made. I tried swapping between the main title scene and the first level a few times to test it. After loading the first level, then the title screen, when I try loading the first level back again the load screen is stuck. The whole thing is working on a coroutine, and after some debugging I figured out the problem was that this coroutine stopped executing in a certain part of the code for some reason.

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

Only during the 3rd loading, right after the while (!unload.isDone) yield return null; line the coroutine just stops executing (I know it because I inserted a Debug.Log inside the while loop and it got called, but I inserted one right after and it did NOT get called).

Any suggestions?

CodePudding user response:

I figured out the problem by myself. The GameManager itself was programmed as a singleton, and since there was a GameManager in both scenes that was messing things up. Had to move the GameManager to a separate scene loaded additively.

  • Related