SceneManager.UnloadSceneAsync returns null

Whenever I attempt to unload a scene using the scene manager, the AsyncCoroutine gets returned as null, so I can’t track its progress. Here’s the code I’m using to try to unload the scene:

    private AsyncOperation asyncUnload;     //The unload Async Operation


    ....
        //Start the unload coroutine, pass in name of the scene I'm trying to unload.
        StartCoroutine(UnloadLevel(SceneManager.GetActiveScene().name));
    ....

    private IEnumerator UnloadLevel(string levelName)
    {
        //asyncUnload = SceneManager.UnloadSceneAsync(levelName);
        //asyncUnload = SceneManager.UnloadSceneAsync(1);
        asyncUnload = SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());
       
        Debug.Log(asyncUnload);

        isSceneUnloaded = false;

        while (asyncUnload.progress < .9)
        {
            yield return null;
        }

        yield break;
    }

Whenever it gets to the debug output, asyncUnload is always null. I’ve tried all three variations of the method, double checked that I’m passing in the correct name, and made sure that the scene I’m currently trying to unload is always index 1. No matter what, it always returns null, so I can’t use the while loop to track its progress.

I’m sure I’m just missing something simple, but I’m pretty perplexed as to why this isn’t working.

Thanks for any help you can offer.

Same issue here, trying to figure out the new UnloadSceneAsync to replace UnloadScene and i’m having tons of issues. It’s almost impossible to get help with scene management, i’m considering staying with UnloadScene and never upgrading Unity again for the duration of the development on my game.

1 Like

I see you set your thread to “Solved” please keep any information that existed there and please post your fix in the comments. We cannot learn if no one teaches. Show us how to fix it, as you would expect of others to show solutions aswell, its the point of the forums.

I’ve set my thread to solved because i just gave up and went with a hacky solution that works with my game’s design, i don’t think it is something people would have benefited from and it’s impossible to delete threads.

Since unloading the current scene completely before activating the next scene seems impossible all i did was loop through all the game objects in the current scene after the screen has faded out and disable them all to prevent them from colliding with the next scene. It works for now but having to do this doesn’t feel right, I just don’t have time to deal with the issue right now.

foreach(GameObject go in SceneManager.GetActiveScene().GetRootGameObjects())
        {
            go.SetActive(false);
        }
2 Likes

I have the same issue. This thread should be kept alive for others to post a solution, since finding the thread in search results and reading through it doesnt offer satisfactory solution atm.

EDIT: the only time that i get null AsyncOperation returned is when i am trying to unload a currently loading scene. I’ve posted it as a question here: How to stop loading of a scene that's loading using SceneManager.LoadSceneAsync ? - Questions & Answers - Unity Discussions

2 Likes

@_watcher Could you update your Unity Answer link?

I encountered this, I was trying to unload the last remaining scene. I guess you have to always have at least one scene active. I got around it by making a new scene with SceneManager.CreateScene() before calling delete on the existing ones.

8 Likes

Thank you!!!

Well, I ran into this problem while I was trying to unload scenes I didn’t need. This was during the Awake method of the first scene. So I started to think that the scene I was trying to remove wasn’t yet fully initialised (or even loaded yet), and thus couldn’t be removed - which makes perfect sense. So, timing is everything,

Luckily I was using Tasks and I simply called “await Task.Yield()” before trying to remove the scene, and the problem was resolved.

I’m not seeing that as the only reason. I have scene P0, it’s fully loaded, and has been running, and I start async loading another scene P1. During the completed event for SceneManager.LoadScene( xxx, Additive ), I call SceneManager.UnloadSceneAsync( P0 ). This returns null. The old scene does in fact unload, but I shouldn’t be getting null here… after all ,the new scene loaded already, or I wouldn’t be getting the event.

Maybe (just maybe) unloading the current active scene is not possible? Try setting the newly loaded scene as the active one and then unload the old scene.

I’ve been struggling with this same issue (UnloadSceneAsync returning null) for about an hour and I just found a solution. Maybe this will be useful to other people.

I created a method to first unload any previously loaded scene and then load the new scene.

public void LoadMyScene(string sceneName)
{
    StartCoroutine(LoadSceneCoroutine(sceneName));
}

private IEnumerator LoadSceneCoroutine(string sceneName)
 {
            //CODE OMITTED: check to see if I had previously loaded a scene
            //CODE OMITTED: call UnloadSceneAsync + wait for it to finish
            //CODE OMITTED: call LoadSceneAsync + wait for it to finish
 }

The source of the problem was that, to test it out, I tried to call the method twice in a row.

void Start()
{
    LoadMyScene("scene1");
    LoadMyScene("scene2");
}

Null was returned by UnloadSceneAsync because the second call to LoadMyScene tried to unload the scene while the first call to LoadMyScene was still trying to load it.

To solve this I created a very primitive queue.

Coroutine sceneLoadingCoroutine;
List<string> coroutineSceneNameQueue = new List<string>();

public void LoadScene(string sceneName)
 {
        if (sceneLoadingCoroutine == null)
        {
                sceneLoadingCoroutine = StartCoroutine(LoadSceneCoroutine(sceneName));
        }
        else
        {
                if (coroutineSceneNameQueue.Contains(sceneName) == false)
                {
                        coroutineSceneNameQueue.Add(sceneName);
                }
        }
 }

private IEnumerator LoadSceneCoroutine(string sceneName)
{
        //CODE OMITTED: unload async old scene + wait
        //CODE OMITTED: load async new scene + wait
        sceneLoadingCoroutine = null;

        CheckCoroutineQueue();
}

private void CheckCoroutineQueue()
{
        if (coroutineSceneNameQueue.Count > 0)
        {
                LoadScene(coroutineSceneNameQueue[0]);
                coroutineSceneNameQueue.RemoveAt(0);
        }
}

Now the scenes are properly loaded and unloaded.

Guh, took me forever to figure out you can’t unload the last loaded scene

You can’t unload the last loaded scene even if it’s not the only one? How so? Can you elaborate? Thanks

You definitively can unload any scene as long as it’s not set as the Active Scene and as long as it has been FULLY loaded.
What you can’t do is cancel an async load operation. Which is a MAJOR setback.

Why does it not work when last scene is DontDestroyOnLoad, either?

I solved this by loading the next scene first, then unloading the current one.

To elaborate,

  private IEnumerator LoadScene(string sceneName)
    {
        string currentScene = SceneManager.GetActiveScene().name;

        //Load the new scene
        yield return StartCoroutine(LoadNew(sceneName));

        //Unload the scene that we're on right now
        yield return StartCoroutine(UnloadCurrent(currentScene));

        yield return null;
    }

    private IEnumerator UnloadCurrent(string currentScene)
    {
        AsyncOperation UnloadOperation = SceneManager.UnloadSceneAsync(currentScene);

        //Wait until the scene is fully unloaded
        while (!UnloadOperation.isDone)
        {
            yield return null;
        }
    }

    private IEnumerator LoadNew(string sceneName)
    {
        AsyncOperation LoadOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);

        while (!LoadOperation.isDone)
        {
            yield return null;
        }
    }
1 Like

I guess things changed in latest versions of Unity.
I also got this problem. the reason was that I am trying to unload a scene which is marked as active.
Active scene is the one on which new game objects are instantiated.
My scenario:
-Start with Scene 1
-Put some objects in DontDestroyOnLoad scene
-Unload Scene 1 - doesn’t unload as it is the initial scene and it is active.
-Load Scene 2 - this one load normally

To fix this you can create a scene in runtime:
public const string RuntimeScene = “Runtime”;
[RuntimeInitializeOnLoadMethod]
static void LoadRuntimeScene()
{
Scene scene = UnityEngine.SceneManagement.SceneManager.CreateScene(RuntimeScene);
UnityEngine.SceneManagement.SceneManager.SetActiveScene(scene);
Debug.LogFormat(“Runtime scene created!”);
}

after this step the above scenario works correctly. Scene 1 is succesfully unloaded.