SceneManager.SetActiveScene does not work [SOLVED/WORKAROUNDS]

It basically doesnt work.

    public void OnLoading(GameStateEvent ev)
    {
        SceneManager.LoadScene(Game, LoadSceneMode.Additive);
        Game_scene = SceneManager.GetSceneByName(Game);
        SceneManager.SetActiveScene(SceneManager.GetSceneAt(1));

    }

aaaaand nothing.
The other scene is still active, and if i manually set active scene in editor it works.
Checked the variables with debugger all proper, Game_scene contains the right scene,
it just doesnt work.

It does not work because the other scene it not loaded at this point.

LoadScene always completes next frame, so you need to wait a frame for the new scene to be fully loaded before you can make it active.

5 Likes

Please take a second to add that info here https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.SetActiveScene.html
thank you!

5 Likes

Ez way to handle this

    public void OnLoading(GameStateEvent ev)
    {
        SceneManager.LoadScene(Game, LoadSceneMode.Additive);
        Game_scene = SceneManager.GetSceneByName(Game);
        StartCoroutine(SetActive(Game_scene));
    }

    public IEnumerator SetActive(Scene scene)
    {
        int i = 0;
        while(i == 0)
        {
            i++;
            yield return null;
        }
        SceneManager.SetActiveScene(scene);
        yield break;
    }
4 Likes

Wow seemingly, now this introduces a whole lot of problems!
Since on that first frame things are initialized that we skip, when we instantiate objects on that frame they are getting instantiated to different scene! I dont think you didnt took such things into account but on first glance it seems a bit messy.

What do you mean things are instantiated in a different scene?
Object are always instantiated in the active scene.

Yes as if i have Init scene, with managers, then i load my game scene, and objects in game scene instantiate objects in Awake, because the active scene still is Init, they will get instantiated in Init. And only after that initial frame its switching active scene. So in my case i have solution of using my own game state events to tell my objects when loading is complete, but majority will have to do something else to solve that.

Yes object will always get instantiated in to the active scene and you cannot switch the active scene before it has been completely loaded. I am afraid that for now you will have to work around this issue.

In order for you to do what you really want i.e. instantiate into the recently loaded scene, even though it is not active, you need to two things.

1: You need a callback to get notified when a scene has been loaded
2: You need Object.Instantiate to take the scene to instantiate to as an argument

This way you don’t need to rely on Awake which can be called at other times than loading.

Point 1 has just been merged to the 5.4 branch, but it is a new feature and will not get back ported. I am hoping to get a new version of instantiate in to 5.4 as well, but I cannot promise it will be there on shipping day.

3 Likes

Thank you.

I’m having this issue as well. There appears to be no way to set the newly loaded scene as the active scene before the objects in the newly loaded scene start doing stuff. This is a big issue if you need objects to instantiate stuff into their own scene, once the scene is loaded.

Would it be possible to activate the scene with the callback before the objects in that scene are activated?

For the mean time, I’ve found a workaround.

  • Create a new empty scene with SceneManager.CreateScene and set it to be the active scene
  • Load the desired scene
  • Once the scene has loaded, merge it with the empty scene, which now has all the initially instantiated objects
  • The source scene was destroyed, so if that was the active scene, you need to set it again.
1 Like

you can use this instead of Awake i guess http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnLevelWasLoaded.html

but i havent tested it, my OnLoadingEnd happens outside of unity pipe.

That doesn’t work for scenes loaded additively. But it looks like 5.4 will improve that as well.
http://forum.unity3d.com/threads/onlevelwasloaded-not-called-at-all.382939/#post-2489139

^^ These are really great improvements. I found thread because I’ve just started using the new SceneManager which Im loving, but was so confused why Instantiate was only creating objects in the active scene. My expectation was that instances would be instantiated into the scene that the monobehaviour (that made the call) belonged to. But what you’ve suggested where you can choose which scene to instantiate in to is even better as it lets everyone decide how they want it to work.

Was this the only purpose of the ‘active scene’, to be the default for instantiated objects? Im struggling to find any info on what it does or why you need to set it or use it other than this recently discovered and unexpected behaviour. I’m just wondering what else I might need to account for, thanks so much for your help!

ps: another work around thats much simpler is to just override the transform parent from the monobehaviour that just instantiated the game object.

No it was not the only purpose. The other purpose is to control which render settings and other scene wide settings to use.

Each scene can have different render settings e.g. Ambient light color. When you switch active scene you also apply the render settings of the new active scene.

Ahh right =) thanks that’s great to know. That’s enough of a hint to know the intention behind the active scene, that it’s basically a way for any global scene settings or scene specific functionality to be used.

I’ve got multiple cameras in multiple scenes, but it only uses the render settings of the active scene, which can look a bit off. Would it be possible for the cameras in each scene to use their scene’s render settings?

StartCoroutine (WaitForSceneLoad (SceneManager.GetSceneByName(sceneToLoad)));
        }
        public IEnumerator WaitForSceneLoad(Scene scene){
            while(!scene.isLoaded){
                yield return null;   
            }
            Debug.Log("Setting active scene..");
            SceneManager.SetActiveScene (scene);
        }

Its working
2 Likes