Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

SceneManager.SetActiveScene does not work [SOLVED/WORKAROUNDS]

Discussion in 'Scripting' started by pointcache, Jan 25, 2016.

  1. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
    It basically doesnt work.

    Code (CSharp):
    1.     public void OnLoading(GameStateEvent ev)
    2.     {
    3.         SceneManager.LoadScene(Game, LoadSceneMode.Additive);
    4.         Game_scene = SceneManager.GetSceneByName(Game);
    5.         SceneManager.SetActiveScene(SceneManager.GetSceneAt(1));
    6.  
    7.     }
    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.
     
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    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.
     
  3. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
  4. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
    Ez way to handle this
    Code (CSharp):
    1.     public void OnLoading(GameStateEvent ev)
    2.     {
    3.         SceneManager.LoadScene(Game, LoadSceneMode.Additive);
    4.         Game_scene = SceneManager.GetSceneByName(Game);
    5.         StartCoroutine(SetActive(Game_scene));
    6.     }
    7.  
    8.     public IEnumerator SetActive(Scene scene)
    9.     {
    10.         int i = 0;
    11.         while(i == 0)
    12.         {
    13.             i++;
    14.             yield return null;
    15.         }
    16.         SceneManager.SetActiveScene(scene);
    17.         yield break;
    18.     }
     
  5. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
    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.
     
  6. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    What do you mean things are instantiated in a different scene?
    Object are always instantiated in the active scene.
     
  7. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
    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.
     
  8. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    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.
     
    KEMBL, yakandco and pointcache like this.
  9. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577
    Thank you.
     
  10. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    280
    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.
     
    Last edited: Feb 12, 2016
    sharkwithlasers likes this.
  11. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    577

    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.
     
  12. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    280
  13. yakandco

    yakandco

    Joined:
    Dec 3, 2014
    Posts:
    90
    ^^ 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.
     
  14. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    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.
     
  15. yakandco

    yakandco

    Joined:
    Dec 3, 2014
    Posts:
    90
    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.
     
  16. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    280
    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?
     
  17. RepoGames

    RepoGames

    Joined:
    Apr 15, 2016
    Posts:
    69
    Code (CSharp):
    1. StartCoroutine (WaitForSceneLoad (SceneManager.GetSceneByName(sceneToLoad)));
    2.         }
    3.         public IEnumerator WaitForSceneLoad(Scene scene){
    4.             while(!scene.isLoaded){
    5.                 yield return null;  
    6.             }
    7.             Debug.Log("Setting active scene..");
    8.             SceneManager.SetActiveScene (scene);
    9.         }
    10.  
    11. Its working
     
    raymondy1 and Victor_Savitskiy like this.