How do I unload additive scenes?

I’m making a game where every round cycles through a different environment scene. I have the additive scene load in with the original scene SetActive containing the game manager and gameplay elements. At the moment, every time the round resets, the new environment just loads on top of the pre-existing scene. What would I need to do to unload or remove the additive scene in order to make room for the new additive scene? I want to do this while always keeping the game manager scene active.

Any help is much appreciated. Thank you.

Note I’m in no way a programmer so simple explanations or example code would be much appreciated.

2 Likes

Have you tried UnloadSceneAsync already?

An easy way to accomplish this is to have everything in the Added scene parented to a single game object. Then when you want to ‘unload’ the added scene you can just destroy that game object.

I’ve successfully used this technique in a number of games I’ve written.

4 Likes

I have, and any attempt to do so results in Unity crashing. It might have something to do with all the other code in the game manager contradicting it.

Interesting. How would I be able to assign the scenes to the game object, then have the same game object respawn and still be the designated game object for the next additive scene?

You don’t create the scene objects parent in the main scene, you design the hierarchy like that in the actual additive scenes themselves.

So for example, every scene that will be loaded additively is designed in the editor with everything childed to a single game object called AddedObjects, and you just delete that game object when you want to ‘unload’ that scene.

This is very straightforward if you only ever have one additive scene loaded at a time.

It would get a little more complicated if you wanted to additively load more than one scene at once and then be able to unload them individually. I’ve never actually done that myself, but thinking it through, as each one is loaded it shouldn’t be too difficult to add that new additives scene’s root object to a static list or dictionary that the additive scene gameobjects are stored in so that they can be easily referenced afterwards, and then remove it from the list/dictionary when you unload it.

However, as Peter77 already mentioned, since the introduction of the multi-scene system none of this should be necessary, as UnloadSceneAsync should actually do the job, and if removing the scene causes a crash it could be due to you continuing to reference something that has just been removed, which would still be the case no matter which method you use to add/remove the scenes. So you’d need to treat that as a separate issue.

2 Likes

So I tried using UnloadSceneAsync and it gave me weird results. It seems to work fine if it’s the same level as the previous one being loaded in, but if it’s a different level being called then the game just stops without loading or unloading anything.

I’ve just tested UnloadSceneAsync with this script which additively loads scene2 and then scene3, and then unloads them in the same order, so it’s unloading scene2 after additively loading scene3 and it doesn’t cause any problems.

IEnumerator Start () {
        yield return new WaitForSeconds(5f);
        SceneManager.LoadScene("Scene2", LoadSceneMode.Additive);
        yield return new WaitForSeconds(5f);
        SceneManager.LoadScene("Scene3", LoadSceneMode.Additive);
        yield return new WaitForSeconds(5f);
        SceneManager.UnloadSceneAsync("Scene2");
        yield return new WaitForSeconds(5f);
        SceneManager.UnloadSceneAsync("Scene3");
    }

It seems like the problem could be related to something in your scenes. Have you tried to see if you can reproduce the problem with simple test scenes?

2 Likes

After you do it, don’t forget Resources.UnloadUnusedAssets(); @ the OnSceneUnloaded callback (that you need to += to from sceneUnloaded)

This is also useful:

4 Likes

Never saw that “IEnumerator Start ()”. Really helped me cut some steps, thank you.

1 Like

I used it and it worked perfectly

2 Likes

That’s agreat idea, but wouldn’t that cause performance issues since the additive scenes are still actually running? Cuz in my case there’s gonna be a lot of them

This is called speculative optimization worry. Don’t do it.

If you have a performance issue (memory, speed, whatever), the ONLY place to start with with the profiler (Window → Analysis → Profiler).

Until then, continue your engineering process and make your game.

5 Likes

I have used LoadScene and UnloadSceneAsync many times with no issue until my additive scene refused to unload.
I was able to fix it by using an IEnumerator to wait 0.1f seconds and then call UnloadSceneAsync. I tried the WaitForEndOfFrame() but that didn’t work. Even though my scene was loaded, I guess it wasn’t fully loaded.

A better solution might be to await LoadSceneAsync and then run my code but waiting for a few milliseconds is working for now.