Search Unity

SceneManager LoadScene Additive AND Set Active

Discussion in 'Scripting' started by NioFox, Jan 20, 2016.

  1. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    So I'm trying out this new multi-scene stuff and running into a problem.
    I want to load some scenes together then set one active. The problem is, if I call SceneManager.SetActiveScene right after the load call, it will return false and do nothing. I could set up a co-routine to check when it's loaded, but I want to avoid those since I ran into some problems with them in my WebGL build. Is there any functionality at all in this new SceneManager to load additively and set active immediately after it's done?

    Here's what the code looks like right now:
    Code (CSharp):
    1. SceneManager.LoadScene("Splash", LoadSceneMode.Additive);
    2. SceneManager.SetActiveScene(SceneManager.GetSceneByName("Splash"));
     
    Last edited: Jan 20, 2016
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    if you're doing an additive sceneload, isn't the specified scene added to the current active one? i.e. it'll be in the active scene once it's loaded anyway?
     
  3. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    Not with the new SceneManager in Unity 5.3.1
    There's a whole multi-scene hierarchy now and the one in bold font is the active one. All instantiated objects get put there. When I make the LoadScene additive call, it keeps the previous scene active. Which brings me to the issue with my current attempt:
    I decided to try the co-routine anyway and it still has a problem - some of the Awake scripts that run in the target scene spawn objects that end up in the wrong scene (the one that's active before I set active to the target scene).
    I noticed the light settings also seem to be dependent on the active scene.
     
    Last edited: Jan 20, 2016
  4. danbruno

    danbruno

    Joined:
    Jun 2, 2013
    Posts:
    1
    I'm having this exact problem. I also tried using LoadSceneAsync with the thought that I'd yield until it said it was done, but it never did! The scene I wanted to load showed up in the hierarchy, but the code never progressed past the LoadSceneAsync call.
     
  5. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @NioFox
    The way scene loading work and always have worked in Unity is that it complete in the next frame (Async version maybe even later), so you cannot immediately change the active scene to the new scene it simply not loaded at that point.

    The right solution is coroutines or some other way of waiting at least one frame for the loading to complete. LoadScene is guaranteed fo complete in the next frame, LoadSceneAsync has no guarantees about completion time.

    @danbruno
    Can you file a bug report with a small project that reproduces the issue, I would like to have a look at it.
     
    Sarai and alimoeeny like this.
  6. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    Thanks for taking the time to respond :)
    I understand the methodology a bit better now and have altered my code to work with it. So far so good.

    I did try LoadSceneAsync first, but I ran in to so many more problems. This thread sums up my experiences: http://forum.unity3d.com/threads/loadsceneasync-loadlevelasync-freeze-at-90-for-large-scenes.379700/
    So I guess I'll have to wait until that is resolved before I can use it again?
     
  7. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @NioFox

    What kind of problems?
    I need some more data in order to figure out what the problem is. The stalls that happens on the main thread should be no different between LoadScene and LoadSceneAsync. Stalling often happens because some data has to be processed on the main thread, like texture and vertex buffer uploading.
     
  8. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    @SteenLund
    Ok, I tried it again. I'm using Unity 5.3.1f1
    Code (CSharp):
    1.         AsyncOperation async;
    2.         async = SceneManager.LoadSceneAsync(sceneWorldMap, LoadSceneMode.Additive);
    3.         GUIManager.instance.guiLoading.setProgress(0, true);
    4.         while (!async.isDone)
    5.         {
    6.             yield return new WaitForEndOfFrame();
    7.             GUIManager.instance.guiLoading.setProgress(async.progress);
    8.         }
    1st test: PC
    The first time I tried, it worked. Then I changed some code and the asyncOperation seems to complete normally, but then the scene appears in the scene manager but doesn't actually load (also tested as standalone build).

    2nd test: WebGL
    After I switched platform it worked again. I tried changing code, still worked.

    3rd test: PC again
    Same problem as first test, but this time it did not work on the first run.

    With previous tests (before initial forum post) I had a similar "worked once but never again" experience, except in that instance the asyncOperation would stall at 90%. The difference with those tests was that I was not using Additive. Also, switching to WebGL helped at first, but then started doing the same thing. So I am worried that this will be the case for my current tests as I continue to work with async.
     
    Last edited: Jan 28, 2016
  9. ddf

    ddf

    Joined:
    Jul 9, 2011
    Posts:
    54
    I am butting my head against the same problem this evening. If allowSceneActivation is set to false on the AsyncOperation returned from LoadSceneAsync, isDone never becomes true and progress stalls at 0.9. Similarly, although a valid Scene object is returned from GetSceneByName after LoadSceneAsync is called, then isLoaded never becomes true on the returned Scene object.

    What I want to do is start an async load of a scene and then set it active after a timed camera move. If allowSceneActivation is true, the scene swap can happen before my camera move is complete, but as @NioFox mentions, code of this form does not work:

    Code (csharp):
    1.  
    2. bool  transitionIsDone;  // set elsewhere when the camera finishes moving
    3. string nextSceneName;
    4.  
    5. void loadNextScene()
    6. {
    7.    nextSceneName = "ALegitSceneName";
    8.    var async = SceneManager.LoadSceneAsync( nextSceneName, LoadSceneMode.Additive );
    9.    async.allowSceneActivation = false;
    10. }
    11.  
    12. void Update()
    13. {
    14.    if ( transitionIsDone )
    15.    {
    16.        Scene nextScene = SceneManager.GetSceneByName( nextSceneName );
    17.        if ( nextScene.isLoaded ) // this will never become true
    18.        {          
    19.            Scene activeScene = SceneManager.GetActiveScene();
    20.            SceneManager.UnloadScene( activeScene.buildIndex );
    21.            SceneManager.SetActiveScene( nextScene );
    22.           nextSceneName = null;
    23.        }
    24.    }
    25. }
    26.  
    If this is not the proper way to use the SceneManager to implement what I want to do, that's fine, but there are literally zero code examples in the documentation for SceneManager to demonstrate proper usage for all of the use-cases it appears to support based on the API itself.
     
    glenneroo, IgorAherne and NioFox like this.
  10. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @ddf

    I think I know what is going on in your case and maybe this is something we should change in Unity.

    Loading both Synchronous and Asynchronous happens on a thread. The thread loads all the required assets and then it loads all the objects from the scene, when it is done progress is 0.9 or 90%, the last 10% is the awake on the main thread.

    So when you set allowSceneActivation to false, the last 10% are never done before you set it back to true. This is why scene.isLoaded never becomes true.

    So when the progress reaches 90% and your camera move is complete and you can set the allowSceneActivation true then scene.isLoaded will become true.

    Another thing, in your script you have to set nextScene active before you unload the previous scene otherwise Unload will set the next scene in the SceneManager as active which might not be the scene you want.
     
  11. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @NioFox

    What was the code you changed that made it break?

    The scene is currently added to the SceneManager as soon as you initiate the load, which we are currently working on changing so it only appears when loading and activation has completed.
     
  12. ddf

    ddf

    Joined:
    Jul 9, 2011
    Posts:
    54
    @SteenLund

    Ok, I see, that's all very helpful. This is what actually works for my situation then:

    Code (csharp):
    1.  
    2. bool  transitionIsDone;  // set elsewhere when the camera finishes moving
    3. string nextSceneName;
    4. AsyncOperation async;
    5.  
    6. void loadNextScene()
    7. {
    8.    nextSceneName = "ALegitSceneName";
    9.    async = SceneManager.LoadSceneAsync( nextSceneName, LoadSceneMode.Additive );
    10.    async.allowSceneActivation = false;
    11. }
    12.  
    13. void Update()
    14. {
    15.    if ( transitionIsDone )
    16.    {  
    17.             Scene nextScene = SceneManager.GetSceneByName( nextSceneName );
    18.             if ( nextScene.IsValid() )
    19.             {  
    20.                 Scene activeScene = SceneManager.GetActiveScene();      
    21.                 SceneManager.SetActiveScene( nextScene );
    22.                 async.allowSceneActivation = true;
    23.                 SceneManager.UnloadScene( activeScene.buildIndex );
    24.                 nextSceneName = null;
    25.             }
    26.    }
    27. }
    28.  
    At the moment, this is still not great because I have not yet migrated my game camera to the master scene that is always loaded. So currently both the scene being unloaded and the scene being loaded have cameras in them. This swap would happen *without* a blank frame when I was previously using LoadSceneMode.Single, but now with this additive mode, which is required to prevent the SceneManager from also unloading my master scene, I wind up with a blank frame where the camera in the first scene has been deleted and the one in the newly loaded scene is not yet initialized (I suppose). I do plan to move the camera to the master scene, as well, so it's perhaps a moot point, but even still.

    I think the problems with the API are more with the lack of documentation and the somewhat misleading SetActiveScene (maybe it should be SetMainScene, since it seems to only impact where new GameObjects wind up). SetActiveScene *sounds* like what I would do to initialize an asynchronously loaded scene, but actually it appears that the only way to actually initialize the scene properly is to hang on to the AsyncOperation and set allowSceneActivation to true, which feels gross to me. I don't want to have to hang on to the AsyncOperation if I'm not running in a Coroutine. It's possible to get at the Scene struct through the SceneManager immediately after LoadSceneAsync is called, so why can't that same struct be used to it initialize the Scene once it finishes the async loading?

    I suspect future Unity users trying to work with this new SceneManager will greatly appreciate it if you add your clarifying comments to the documentation.
     
    glenneroo and IgorAherne like this.
  13. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @ddf

    Hmm I don't think the call to SetActiveScene before allowing scene activation actually works. You should delay that call until scene.isLoaded is true.

    Can't your camera/blank frame issue be solved by wainting for both to be completely loaded but having one disabled. Then you can enable the new camera then disable the old camera?

    Your remarks on SetActiveScene vs SetMainScene is something we can take in to consideration.
     
  14. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    @SteenLund
    The code I changed did not appear to be of any consequence. I remember changing it back but still getting the same problem. The code snippet I pasted earlier is basically the whole point of failure. Works with the editor set to WebGL (for now), doesn't work when editor is set to PC. I know that isDone gets to true because code after that executes, but the scene is not loaded.
     
  15. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    Hi, I'm not getting any response from Unity about the LoadSceneAsync taking 15 times longer on an IOS device than LoadScene on the same device. Have you tested async on IOS?
     
  16. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    @arkon
    Unfortunately I have absolutely no iOS hardware to test on.
     
  17. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    That sounds really strange, can you file a bug report with a project attached which reproduces the issue?
     
  18. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    oops sorry that reply was meant for SteenLund

    There is a huge bug in the async loading and Unity just won't acknowledge the problem.
     
  19. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    I have begun building a separate test project to reproduce the error. So far it is still working. As far as I can tell, the major difference between this and my main project is a lack of meaty assets (images, music, etc) to load in the scenes. I'm going to keep adding to it until the problem occurs then file the bug report.

    Update: Ok, after various unsuccessful attempts to reproduce the issues I imported a scene from my main project and BAM - we're stuck at 90%. I am going to try stripping the scene down piece-by-piece to see if I can pin-point an exact cause.
    Update: Interesting discovery - if I pause play mode after it sticks at 90%, then unpause, it will finish loading and run normally. Addendum: Turns out you have to pause for more than a split second. When I double-click the pause button, it doesn't work. But if I pause for something like a full second, it will finish loading.
    Update: It seems like it doesn't even matter what's in the scene itself, but what's in your assets folder. I have a weird feeling that either the terrain or these animated .sbar files I'm using might have something to do with it.
    Update: After prepping a scrubbed project folder (deleted Library and solution files) and trying again, it seems that the problem only starts after the scene with the terrain and .sbar assets is loaded for the first time. From that point on, all scenes fail regardless of content.
    Update: Okay, it is the .sbar files. I will submit this bug report now. I wonder what other types of assets could cause this problem?
    Final Update: Bug report submitted: https://fogbugz.unity3d.com/default.asp?765988_k6a2gkbeko8nk11p
     
    Last edited: Feb 4, 2016
    Stralor and arkon like this.
  20. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    hi,

    I am glad there is this thread.. I was starting to bang my head on the keyboard...


    I am really surprised the whole loading is not properly exposed with events and delegates, we shoudl be able to have a "Scene" Object instance that call us back when loading, activated, etc etc. The basics....

    Bye,

    Jean
     
    Miso99, nco2k, glenneroo and 3 others like this.
  21. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @Jean Fabre

    Yes I know, the callbacks are coming, they have been implemented but I dont know when they will ship
     
    Johannski, hopeful and NioFox like this.
  22. Verkel

    Verkel

    Joined:
    Jun 2, 2013
    Posts:
    4
    Hi,

    I'm also having trouble with this. When loading a scene additively it's not set as active, and Awake() and Start() methods on the loaded scene insert new GameObjects to the previous scene. I'd like them end up in the newly loaded scene. SceneManager.SetActiveScene() can be called to set the scene active, but there seems no way to call it before the scripts have been initialized in the scene.

    @SteenLund Is there any way to achieve this currently? I don't see any definite answer to this in the thread. If not, when will this be addressed?

    Also, when writing a editor script to load scene setups, I found another issue. Calling EditorSceneManager.RestoreSceneManagerSetup() always sets the first scene referred in the SceneSetup array as active in the editor (even though first scene isActive=false, and the second isActive=true). In this case you can work around it by calling SetActiveScene() immediately afterwards. This happens as well when you return from playmode or relaunch Unity editor, I'm guessing this same API is called at those points.

    My use case for first scene inactive, second active? As per docs suggestion, I put shared managers in one scene (the first one). The second scene is a gameplay scene. It requires the managers initialized beforehand. Initialization order seems to be determined by scene order in the editor, so the shared managers scene has to be first. However, the gameplay scene needs to be active in the editor to display its lightmaps correctly.

    Just thought to describe my situation a bit to cover more use cases for the development of this multi scene feature. It's potentially very useful in my game, but the initialization problems may make it impossible to use for me.
     
  23. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Which version of Unity are you using? Sounds like something we have fixed
     
  24. Verkel

    Verkel

    Joined:
    Jun 2, 2013
    Posts:
    4
    5.3.3f1. That should be the latest release, right?
     
  25. FiveFingers

    FiveFingers

    Joined:
    Oct 15, 2009
    Posts:
    541
    5.3.3p3 is the latest one (11 March), try to browse the fixes of the last 3 patches to see if this was fixed.
     
  26. Gaming-Dudester

    Gaming-Dudester

    Joined:
    Apr 12, 2015
    Posts:
    3
    the new unity sux. i liek the Application.Loadlevel so much more
     
  27. TrimeCore

    TrimeCore

    Joined:
    Feb 5, 2016
    Posts:
    1
    Try this, work for me (Unity 5.3.4f1)

    Code (CSharp):
    1. IEnumerator loadNextScene(){
    2.         string name = "ALegitSceneName";
    3.         AsyncOperation _async = new AsyncOperation();
    4.         _async = SceneManager.LoadSceneAsync(name, LoadSceneMode.Additive);
    5.         _async.allowSceneActivation = false;
    6.  
    7.         while(!transitionIsDone){
    8.             yield return null;
    9.         }
    10.  
    11.         _async.allowSceneActivation = true;
    12.  
    13.         while (!_async.isDone) {
    14.             yield return null;
    15.         }
    16.  
    17.         Scene nextScene = SceneManager.GetSceneByName( name );
    18.         if (nextScene.IsValid ()) {
    19.             SceneManager.SetActiveScene (nextScene);
    20.             SceneManager.UnloadScene (SceneManager.GetActiveScene ().name);
    21.         }
    22.     }
     
    Neyxo likes this.
  28. alimoeeny

    alimoeeny

    Joined:
    Feb 27, 2016
    Posts:
    9
    So why this is not mentioned in the documentation anywhere? I mean I've been reading the docs all day and no where it says when you call LoadScene you need to wait at least one frame. While the freaking call returns void.
    BUT THANK YOU FOR MENTIONING IT HERE. really.
     
    RaineB, IgorAherne and hessel_mm like this.
  29. s_guy

    s_guy

    Joined:
    Feb 27, 2013
    Posts:
    102
    Given a partial scene load via the following...

    Code (CSharp):
    1.         _preLoadNextSceneOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
    2.         _preLoadNextSceneOperation.allowSceneActivation = false;
    ...is it possible / appropriate to:
    1. Unload that partially loaded scene? I tried UnloadScene and it appeared to fail silently. The scene claims to be IsValid, but attempting to destroy (not fully loaded) objects within it causes an error. I presume and hope there is some way to undo this scene load without having to let it finish and activate.
    2. Activate a partially loaded scene out of order? An Answers response to someone else's question suggests not. I would like to be able to have more than one preloaded scene available, finish loading only when necessary, and unload preloaded scenes only when necessary.
    Who do I want to do this? I want to improve load times in the game by preloading a scene before the player commits to that scene change. If the player moves toward another scene, I want to preload that other scene instead and have it available to be activated next. These are scenes that are not meant to coexist as active scenes at the same time or be merged.

    If anyone has some tips or best practices for this kind of paradigm, please let me know.
     
    Last edited: Jun 25, 2016
  30. Zireael07

    Zireael07

    Joined:
    Apr 27, 2016
    Posts:
    47
    I don't think there is such a thing as a 'partially loaded scene' - it's either loaded or not.

    That said, I'm running into the same problem with switching to an additively loaded scene.
     
  31. s_guy

    s_guy

    Joined:
    Feb 27, 2013
    Posts:
    102
    @Zireael07 See the documentation on allowSceneActivation for what I'm describing as a "partially loaded scene".
    https://docs.unity3d.com/ScriptReference/AsyncOperation-allowSceneActivation.html

    "When allowSceneActivation is set to false then progress is stopped at 0.9. The isDone is then maintained at false. When allowSceneActivation is set to true isDone can complete."

    It works, but there is apparently no way to back out of it. All you can do is allow it to finish, which will force it to be the active scene. You can also start, but not complete the load for another scene until you allow this to happen. This seems odd, so I'm hoping to be corrected.

    As is, the only practical use cases for async load additive seem to be:
    1. "Hide load times on a mutually-exclusive scenes game world" Start an additive async partial load at the point where the scene change is fully committed to, so you can do something visual meanwhile in the current scene to conceal some of the load time. Then unload the previous scene.
    2. "Seamless world model" Set up content such that the current scene doesn't need to be unloaded when the extra scene is added in. Then you can lazily unload scenes that are far away from play. Scene files need to have appropriate sized chunks of game content for this to work well (and not have unreasonable memory demands).
    It doesn't currently seem appropriate for "async pre-load current most likely next scene", because you can't back out as far as I can tell.
     
    Last edited: Jun 30, 2016
  32. BackwoodsGaming

    BackwoodsGaming

    Joined:
    Jan 2, 2014
    Posts:
    2,229
    I was attempting to do something like #2 and I couldn't even get that to work. I think I was trying to use SetActiveScene in my method where I wanted to switch to the loaded scene whereas I probably needed to just move code outside of my async method and make sure my scene variable is declared at the class level. Then just do checks for progress at 0.9 and toggle allowSceneActivation to true when I actually want to load the scene.

    What I'm trying to do is set up video capture to go through each of my scenes, have the camera follow a certain route, and then move to the next scene to rinse and repeat. Ideally I want the next scene loaded and ready to go by the time the route is finished. So going to try it that way this weekend when I have time to dig into it.

    Really, it would be nice to have more code examples/documentation for this stuff. Trying to figure this stuff out with what little bit is out there and lack of examples is almost impossible for those of us totally new to the async load concept. Maybe those who used the LoadLevel stuff before, it might not be as bad. But for someone coming into the concept fresh, it really isn't documented well. :(
     
  33. duencil

    duencil

    Joined:
    Dec 17, 2012
    Posts:
    91
    Well, I'm running into the same problems as the others on this thread. I'm trying to follow the advice in the Multi Scene Editing documentation that says:

    I've worked around certain API shortcomings, like the fact that the SceneSetup class isnt serializable (needing a wrapper to save multi scene setups), the fact that the runtime SceneManager doesnt provide a list of scenes that can be loaded - for some reason it only produces a list of those that were already loaded, and the fact that additive scene loading does not cause OnLevelWasLoaded to be called on existing gameobject components.

    I am loading my managers scene first, and then my game level after, because it depends on the managers. I'm running into the same problems as @Verkel, where my game level has a bunch of startup logic (executed in Awake and Start calls) that causes the principal level objects to be instantiated, but they are being added to the managers scene as it is the active scene at that point. I dont understand why the loading scene cant be made the active scene prior to the object Awake/Start (i.e at the 0.9 async loading point). After all it is so in the non-additive case. It seems to work if made the Active scene from a script with a high execution order in the Start call, but thats a clumsy workaround. Otherwise I'm forced to move setup logic out of Awake / Start and put it into Update or a delayed called function.

    Also like @Verkel I'm finding that EditorSceneManager.RestoreSceneManagerSetup() always sets the first scene to be active, regardless of which is active in the passed SceneSetup, and that switching platform or entering play mode in the editor changes the first scene to be active (which persists after leaving play mode), making the option to "Set Active Scene" in the editor pointless. I am testing with 5.3.5p6. If this has been fixed @SteenLund can you let us know in what version? And I'd be interested if anything has been improved in the 5.4 betas.
     
    Last edited: Jul 24, 2016
  34. duencil

    duencil

    Joined:
    Dec 17, 2012
    Posts:
    91
    As I touched on above, by the time Start is called on new scene objects, it is fine to set that new scene as active. But unfortunately theres no way a coroutine managing the async loading can intercept that moment even if the AsyncOperation.isDone is set to true by then, as theres no available yield return that takes us to a point in the Execution Order between the new objects' Awake and Start calls. This would also be the proper moment to call a replacement for OnLevelWasLoaded for additive scenes, so its doubly unfortunate.
     
  35. duencil

    duencil

    Joined:
    Dec 17, 2012
    Posts:
    91
    For the benefit of anyone else arriving late to this, I've tried 5.4 P1, and there are some improvements I can report. There are new events you can hook onto in SceneManager to get callbacks when new scenes are loaded, unloaded, or made the active scene. I havent tried these out yet to see how they help with timing, but with these we should be able to replace the now deprecated OnLevelWasLoaded.

    The SceneSetup class has been made serializable which is good, but it probably still needs to be wrapped in a custom class for any runtime use because it exists in the UnityEditor namespace. EditorSceneManager.RestoreSceneManagerSetup() is still broken, but in a new way. Now if the first scene is not the active one it just skips opening it rather than the old bug of making it active. Best fix though is that on exiting play mode in the editor, it no longer sets the first scene to be the active one, that was getting really annoying for our scene setups.

    For anyone interested the correct editor functionality of RestoreSceneManagerSetup() would be:
    Code (CSharp):
    1.  public static void MyRestoreSceneSetup(SceneSetup[] sceneSetups)
    2.     {
    3.         for (int i = SceneManager.sceneCount-1; i>=0; i--)
    4.             EditorSceneManager.CloseScene(SceneManager.GetSceneAt(i), true);
    5.        
    6.         List<Scene> sceneList = new List<Scene>(sceneSetups.Length);
    7.         for (int i = 0; i < sceneSetups.Length; i++) {
    8.             SceneSetup sceneSetup = sceneSetups[i];
    9.             sceneList.Add(EditorSceneManager.OpenScene(sceneSetup.path, (i == 0) ? OpenSceneMode.Single : OpenSceneMode.Additive));
    10.         }
    11.  
    12.         for (int i = 0; i < sceneSetups.Length; i++) {
    13.             if (sceneList[i].IsValid()) {
    14.                 SceneSetup sceneSetup = sceneSetups[i];
    15.                 if (!sceneSetup.isLoaded)
    16.                     EditorSceneManager.CloseScene(sceneList[i], false);
    17.                 else if (sceneSetup.isActive)
    18.                     SceneManager.SetActiveScene(sceneList[i]);
    19.             }
    20.         }
    21.     }
     
    laurentlavigne likes this.
  36. Silverleaf

    Silverleaf

    Joined:
    Sep 19, 2013
    Posts:
    3
    It would be nice if this explanation was on the respective funciton calls in the documentation. As of Unity 5.4, it's still says nothing about what you said in the docs. I figured it out before reading this because of past experience with this, but the docs were 0 help in this regard.
     
  37. brunoleos

    brunoleos

    Joined:
    May 14, 2014
    Posts:
    30
    I've just tested the SceneManager.sceneLoaded event, and inside the handler I expected that scene.isLoaded from the scene received as argument should be true, but that's not the case.

    Shouldn't the event only be fired if the scene is completely loaded? I'm trying to set the scene as active after loading it, and the sceneLoaded event seems to be the best method for that.

    The handler code:
    Code (CSharp):
    1.     private void OnSceneLoaded(Scene scene, LoadSceneMode loadMode) {
    2.         Debug.Log("event: " + Time.frameCount);
    3.         Debug.Log(SceneManager.SetActiveScene(scene)); // this returns false
    4.         Debug.Log("OnSceneLoaded: " + scene.name +
    5. " loaded as " + loadMode +
    6. ". Active is " + SceneManager.GetActiveScene().name); // I expected that active become the loaded scene
    7.     }
    Tested on 5.4.1f1, downloading 5.4.2f2 now.

    EDIT: Just tested 5.4.2f2, same result
     
    Last edited: Nov 10, 2016
  38. duencil

    duencil

    Joined:
    Dec 17, 2012
    Posts:
    91
    yeah, I am using that event too for setting my main scene active and it works well, getting called before the Start of newly loaded objects, which is helpful, so that objects can then do their initialisation as part of the "active" scene
     
  39. brunoleos

    brunoleos

    Joined:
    May 14, 2014
    Posts:
    30
    @duencil,
    So you can set the scene active inside the handler of sceneLoaded?
    As I said in my question, my problem is that the scene loaded status is false, even inside the handler, so that I cannot change it to the active scene.
    Are you setting active the scene given at the argument of the UnityAction?
     
  40. duencil

    duencil

    Joined:
    Dec 17, 2012
    Posts:
    91
    No, you're right. I also have some old workaround code I wrote (from before the events were added) still in place and that is what is actually setting the new scene to be active when needed. The attempt to do it from the sceneLoaded event is failing.
     
  41. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @brunoleos

    When you get the sceneLoaded callback the scene is actually fully loaded, the bool just hasn't been flipped yet. Which unforunately prevents you from setting the scene active.

    5.5 will have the flag set correctly when sceneLoaded is called
     
    brunoleos likes this.
  42. UrsHanselmann

    UrsHanselmann

    Joined:
    Jan 28, 2014
    Posts:
    13
    Any chance we could also get this on your dev's radar for the next 5.4 patch?

    We are also just dealing with this issue and I'm really no big fan of being forced to upgrade to a beta version just because of a small issue like that - been there and done that far too often with Unity :p
     
  43. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @ChrisHanselmann
    5.5 is not in beta any more :)

    I will look into if this can be back ported
     
  44. kamac

    kamac

    Joined:
    Mar 21, 2014
    Posts:
    13
    @SteenLund I tried it out in 5.5.0f3, but the boolean is still set to false during on scene loaded callback.

    My code:
    Code (CSharp):
    1. public void OnButtonPressed()
    2. {
    3.     SceneManager.sceneLoaded += OnGameLoaded;
    4.     SceneManager.LoadScene("Game", LoadSceneMode.Additive);
    5. }
    6.  
    7. private void OnGameLoaded(Scene scene, LoadSceneMode mode)
    8. {
    9.     SceneManager.sceneLoaded -= OnGameLoaded;
    10.  
    11.     Debug.Log(scene.isLoaded); // prints false
    12.     SceneManager.SetActiveScene(scene); // doesn't work, because scene.isLoaded = false
    13.     SceneManager.UnloadSceneAsync("MainMenu");
    14. }
     
    Last edited: Dec 1, 2016
  45. Korigoth

    Korigoth

    Joined:
    Jul 21, 2014
    Posts:
    105
    i have the same problem it's not fixed
     
  46. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hmm I will have to investigate, I am pretty sure I had this back ported to 5.5 before shipping
     
  47. greg-harding

    greg-harding

    Joined:
    Apr 11, 2013
    Posts:
    524
    @SteenLund I just tried testing some of the async loading stuff again in 5.5.0p1 and it's not fixed yet. The scene.isLoaded returns false during the sceneLoaded callback.

    The SceneManager docs have been updated to describe that when using 'allowSceneActivation = false' progress will stop at 0.9 when loading is complete prior to initialisation. However, the docs are now missing all of the events like sceneLoaded, sceneUnloaded etc.

    5.4: https://docs.unity3d.com/540/Documentation/ScriptReference/SceneManagement.SceneManager.html
    5.5: https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.html

    As you can see from this thread and a few others (and maybe Unity Answers and Stack Overflow if you've looked), the SceneManager API isn't easy to get right without writing lots of test code to check the events and states, particularly the progress value and isDone not quite matching what devs might expect at certain parts of the process. Have you considered using some enum states like other parts of the API use, or could you perhaps tweak some of the naming to make things a bit more obvious?

    Also, the docs being out of date and missing important things like the loading events makes things a bit harder to figure out too :)
     
  48. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    I'm trying to pre-load multiple neighboring scenes and only activate the one the player chooses and cancel the others as i only want one scene active at a time, is this really impossible to do at the moment?
     
    tanoshimi likes this.
  49. TieSKey

    TieSKey

    Joined:
    Apr 14, 2011
    Posts:
    225
    Testing on 5.6, it seems the sceneLoaded event triggers when the scene is loaded and activated, it fixes the "isLoaded=false" issue but we still have no way to "set as active" an additive loaded scene before it "activates" and all the Start/Awake methods spawn things on the wrong place.
     
    PuzzledBoy and laurentlavigne like this.
  50. MrDude

    MrDude

    Joined:
    Sep 21, 2006
    Posts:
    2,569
    Quick change of topic, if you don't mind...

    In the docs it says not to use DontDestroyOnLoad for manager objects but rather to load it via a Manager Scene using the LoadSceneMode.Additive method. So real quick question.... If the very first scene I load is my bootstrap scene and it contains my manage objects, how do I make my first scene a Manager Scene ?

    Right now, all I see is the option to do exactly what you said NOT to do and use DontDestroyOnLoad on my objects... or create one scene that does absolutely nothing but load what was supposed to be my first scene.

    Thanks