Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

SceneManager.UnloadSceneAsync returns null

Discussion in 'Scripting' started by PatrickReynolds, May 25, 2017.

  1. PatrickReynolds

    PatrickReynolds

    Joined:
    Nov 19, 2014
    Posts:
    17
    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:

    Code (CSharp):
    1.  
    2.     private AsyncOperation asyncUnload;     //The unload Async Operation
    3.  
    4.  
    5.     ....
    6.         //Start the unload coroutine, pass in name of the scene I'm trying to unload.
    7.         StartCoroutine(UnloadLevel(SceneManager.GetActiveScene().name));
    8.     ....
    9.  
    10.     private IEnumerator UnloadLevel(string levelName)
    11.     {
    12.         //asyncUnload = SceneManager.UnloadSceneAsync(levelName);
    13.         //asyncUnload = SceneManager.UnloadSceneAsync(1);
    14.         asyncUnload = SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());
    15.        
    16.         Debug.Log(asyncUnload);
    17.  
    18.         isSceneUnloaded = false;
    19.  
    20.         while (asyncUnload.progress < .9)
    21.         {
    22.             yield return null;
    23.         }
    24.  
    25.         yield break;
    26.     }
    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.
     
    Last edited: May 25, 2017
  2. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    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.
     
    anycolourulike likes this.
  3. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    825
    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.
     
  4. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    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.

    Code (CSharp):
    1. foreach(GameObject go in SceneManager.GetActiveScene().GetRootGameObjects())
    2.         {
    3.             go.SetActive(false);
    4.         }
     
    anycolourulike and TaleOf4Gamers like this.
  5. _watcher_

    _watcher_

    Joined:
    Nov 7, 2014
    Posts:
    259
    Last edited: Jul 13, 2017
  6. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @_watcher_ Could you update your Unity Answer link?
     
  7. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    209
    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.
     
    Last edited: Mar 12, 2022
  8. LucianoMacaDonati

    LucianoMacaDonati

    Joined:
    Dec 31, 2012
    Posts:
    10
    Thank you!!!
     
  9. VOTRUBEC

    VOTRUBEC

    Joined:
    Dec 17, 2014
    Posts:
    97
    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.
     
  10. EricHFrazer

    EricHFrazer

    Joined:
    Jun 30, 2020
    Posts:
    20
    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.
     
  11. atomicjoe

    atomicjoe

    Joined:
    Apr 10, 2013
    Posts:
    1,866
    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.
     
  12. BlackRainbowFT

    BlackRainbowFT

    Joined:
    Nov 28, 2015
    Posts:
    18
    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.

    Code (CSharp):
    1. public void LoadMyScene(string sceneName)
    2. {
    3.     StartCoroutine(LoadSceneCoroutine(sceneName));
    4. }
    5.  
    6. private IEnumerator LoadSceneCoroutine(string sceneName)
    7.  {
    8.             //CODE OMITTED: check to see if I had previously loaded a scene
    9.             //CODE OMITTED: call UnloadSceneAsync + wait for it to finish
    10.             //CODE OMITTED: call LoadSceneAsync + wait for it to finish
    11.  }
    12.  
    The source of the problem was that, to test it out, I tried to call the method twice in a row.

    Code (CSharp):
    1. void Start()
    2. {
    3.     LoadMyScene("scene1");
    4.     LoadMyScene("scene2");
    5. }
    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.

    Code (CSharp):
    1. Coroutine sceneLoadingCoroutine;
    2. List<string> coroutineSceneNameQueue = new List<string>();
    3.  
    4. public void LoadScene(string sceneName)
    5.  {
    6.         if (sceneLoadingCoroutine == null)
    7.         {
    8.                 sceneLoadingCoroutine = StartCoroutine(LoadSceneCoroutine(sceneName));
    9.         }
    10.         else
    11.         {
    12.                 if (coroutineSceneNameQueue.Contains(sceneName) == false)
    13.                 {
    14.                         coroutineSceneNameQueue.Add(sceneName);
    15.                 }
    16.         }
    17.  }
    18.  
    19. private IEnumerator LoadSceneCoroutine(string sceneName)
    20. {
    21.         //CODE OMITTED: unload async old scene + wait
    22.         //CODE OMITTED: load async new scene + wait
    23.         sceneLoadingCoroutine = null;
    24.  
    25.         CheckCoroutineQueue();
    26. }
    27.  
    28. private void CheckCoroutineQueue()
    29. {
    30.         if (coroutineSceneNameQueue.Count > 0)
    31.         {
    32.                 LoadScene(coroutineSceneNameQueue[0]);
    33.                 coroutineSceneNameQueue.RemoveAt(0);
    34.         }
    35. }
    Now the scenes are properly loaded and unloaded.
     
  13. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    286
    Guh, took me forever to figure out you can't unload the last loaded scene
     
  14. esteban16108

    esteban16108

    Joined:
    Jan 23, 2014
    Posts:
    158
    You can't unload the last loaded scene even if it's not the only one? How so? Can you elaborate? Thanks
     
  15. atomicjoe

    atomicjoe

    Joined:
    Apr 10, 2013
    Posts:
    1,866
    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.
     
  16. K0ST4S

    K0ST4S

    Joined:
    Feb 2, 2017
    Posts:
    35
    Why does it not work when last scene is DontDestroyOnLoad, either?
     
  17. foresightvirtualreality

    foresightvirtualreality

    Joined:
    Apr 7, 2020
    Posts:
    1
    I solved this by loading the next scene first, then unloading the current one.

    To elaborate,

    Code (CSharp):
    1.   private IEnumerator LoadScene(string sceneName)
    2.     {
    3.         string currentScene = SceneManager.GetActiveScene().name;
    4.  
    5.         //Load the new scene
    6.         yield return StartCoroutine(LoadNew(sceneName));
    7.  
    8.         //Unload the scene that we're on right now
    9.         yield return StartCoroutine(UnloadCurrent(currentScene));
    10.  
    11.         yield return null;
    12.     }
    13.  
    14.     private IEnumerator UnloadCurrent(string currentScene)
    15.     {
    16.         AsyncOperation UnloadOperation = SceneManager.UnloadSceneAsync(currentScene);
    17.  
    18.         //Wait until the scene is fully unloaded
    19.         while (!UnloadOperation.isDone)
    20.         {
    21.             yield return null;
    22.         }
    23.     }
    24.  
    25.     private IEnumerator LoadNew(string sceneName)
    26.     {
    27.         AsyncOperation LoadOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
    28.  
    29.         while (!LoadOperation.isDone)
    30.         {
    31.             yield return null;
    32.         }
    33.     }
    34.  
     
  18. EugenAxenoi

    EugenAxenoi

    Joined:
    Dec 12, 2012
    Posts:
    2
    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.