It's impossible to async load a scene then have it wait while unloading another?

I’m updating my scene management code, and I thought it would be good to start asynchronously loading the next scene while the current one ends, but I’ve encountered a problem.

For context, I’ve got scriptable objects that hold scene info and transitions, and I’m doing all of this from a manager scene that stays loaded.

Here’s what I had in mind:

SceneManager.SetActiveScene(managerScene.scene);
AsyncOperation newSceneLoad = SceneManager.LoadSceneAsync(newScene.scene.buildIndex, LoadSceneMode.Additive);
//This keeps it from activating while the first scene finishes
newSceneLoad.allowSceneActivation = false;

//Fade out the current scene    
yield return currentScene.EndScene();
    			
AsyncOperation unload = SceneManager.UnloadSceneAsync(currentScene.scene.buildIndex);
yield return unload; //Should wait for the first scene to unload...

newSceneLoad.allowSceneActivation = true; //This line won't work here...
yield return newSceneLoad;

//Fades in    
yield return newScene.StartScene();

Here I’m using UnloadSceneAsync because UnloadScene is depreciated, but it doesn’t work when used together with LoadSceneAsync. On this page it says: Unity - Scripting API: AsyncOperation.allowSceneActivation

if a
LoadSceneAsync.allowSceneActivation is
set to false, and another
AsyncOperation (e.g.
SceneManager.UnloadSceneAsync ) is
initialized, the last operation will
not be called before the first
allowSceneActivation is set to true.

That means I have to move the “allowSceneActivation = true” line up above the “yield return unload” line for unload to continue. But that means the scenes will overlap-- the first one will finishing loading before the second one is removed. And indeed when I do that I get some “There are 2 audio listeners in the scene” warnings, since the cameras for both scenes are present for a few frames.

So although it makes sense that Async loading could be used like this, it doesn’t seem to be possible. Can anyone confirm this or let me know a different way to do it?

@adsilcott, I was trying to do exactly as you were:

  1. Load the new scene (but don’t allow it to activate on load).
  2. Unload the old scene.
  3. Activate new scene.

… and I was experiencing the same issue with the AsyncOperation being stalled due to allowSceneActivation being false.

My solution was to destroy all root objects on the old scene, activate the new scene, and then unload the old scene:

  1. Load the new scene (but don’t allow it to activate on load).
  2. Destroy all root objects on the old scene
  3. Activate new scene.
  4. Unload the old scene.

This allows the old scene to unload, because the new scene is no longer blocking the AsyncOperation queue. And the old scene objects being destroyed prevents the duplicate objects, such as audio listeners.

For the record, I’m reloading a scene (Additive) layer. If I were to unload the old scene before loading the new scene, Unity would release scene resources only to immediately reload them, increasing load times. However, loading the new scene while the old scene is loaded allows Unity to skip loading certain assets that exist in the old scene, which speeds up load times.

I’m also using the new Addressables.LoadSceneAsync(assetReference, mode, activateOnLoad) instead of SceneManager.LoadSceneAsync() methods, but I expect they should work the same way. I am unloading the old scene with SceneManager.UnloadSceneAsync(scene).

Anyhow, I hope that helps anyone interested in cleanly loading or reloading a scene without overlapping an old scene that should be replaced.