Search Unity

OnLevelWasLoaded() not called at all

Discussion in 'Editor & General Support' started by Wrymnn, Jan 30, 2016.

  1. Wrymnn

    Wrymnn

    Joined:
    Sep 24, 2014
    Posts:
    384
    I know OnLevelWasLoaded() doesn`t work when you load only one scene, since it isn`t taken as new scene, but, the problem lies even with loading Scene Additive:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class GameManager : MonoBehaviour
    6. {
    7.     void Start()
    8.     {
    9.         SceneManager.LoadScene("Scene_2", LoadSceneMode.Additive);
    10.     }
    11.  
    12.     void OnLevelWasLoaded(int level)
    13.     {
    14.         Debug.Log("Something loaded");
    15.     }
    16. }
    17.  
    The OnLevelWasLoaded() is not called, I tried as you see with Debug.Log and breakpoint. The second scene is normally loaded additive, and appears in Hierarchy, which I can see.

    Where could be a problem? Is OnLevelWasLoaded() not working in Editor?
     
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hi,

    It is correct that OnLevelWasLoaded is not called for scenes loaded additively.

    Unless this has regressed since 5.2 it is not something that will be fixed. In 5.2 you could call Application.LoadLevelAddtive and this did not call OnLevelWasLoaded as far I know.

    In 5.4 we have added some new events to SceneManager. SceneManager.sceneLoaded, SceneManager.sceneUnloaded and SceneManager.activeSceneChanged. These will also be called for scene loaded additively.
     
  3. Wrymnn

    Wrymnn

    Joined:
    Sep 24, 2014
    Posts:
    384
    Hey thanks for the upcoming news! Cannot wait for 5.4!
     
  4. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    yeeeeeeah. We have to wait another month for literally VITAL thing. I dunno, another spit in the face.
     
  5. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @pointcache

    I am not sure I understand what the problem is. OnLevelWasLoaded did not regress in any way and 5.4 beta is available to every one even Personal Edition users.
     
  6. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    ooops didnt know about that. :|

    what im talking about is the delay between rolling out scene manager and

    SceneManager.sceneLoaded, SceneManager.sceneUnloaded and SceneManager.activeSceneChanged


    events.

    what im doing right now is throwing a special object that raises event to game manager onEnable, basically notifying that scene has loaded from withing the scene, very hacky.
     
  7. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    @pointcache it was announced at GDC http://blogs.unity3d.com/2016/03/15...-and-more-the-unity-5-4-public-beta-is-ready/

    Any way, yes SceneManager shipped with some, in hindsight obvious, features missing. We are working hard on adding these features and fixing the bugs and workflow issues that have been reported. Most bug fixes are being back ported to 5.3 and shipped in the patches but new features are not back ported as we don't want to introduce new features in patches, so for features you will have to use the beta releases.
     
  8. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Thanks man, this really tickles my fancy. IM PLEASED NOW. :D
     
  9. Orolo

    Orolo

    Joined:
    Dec 5, 2012
    Posts:
    5
    hm, i just switched to 5.4beta and tried SceneManager.sceneLoaded, but it seems it gets called before the scene is actually loaded...

    I have a ManagerScene that has a GameObject with the following MonoBehavior on it:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3. using System.Collections;
    4.  
    5. public class LoadLevel : MonoBehaviour {
    6.     public static string currentLevel = "lvl1";
    7.    
    8.     void Awake () {
    9.         SceneManager.sceneLoaded += SceneLoaded;
    10.         SceneManager.activeSceneChanged += InitializeNextScene;
    11.         if (SceneManager.sceneCount < 2)
    12.         {
    13.             SceneManager.LoadScene(currentLevel, LoadSceneMode.Additive);
    14.         }
    15.         //StartCoroutine(SetActive(currentLevel));
    16.     }
    17.  
    18.     void SceneLoaded(Scene scene, LoadSceneMode m)
    19.     {
    20.         Debug.Log("Scene loaded: " + scene.name + " in mode: " + m); //scene.name is lvl1, as expected
    21.        
    22.         Debug.Log(Time.frameCount + "Active Scene: " + SceneManager.GetActiveScene().name);
    23.         //ManagerScene is active, as expected
    24.        
    25.         SceneManager.SetActiveScene(scene);
    26.         Debug.Log("is scene loaded: " + scene.isLoaded);
    27.         //this prints that scene is *not* loaded; isn't the whole point of
    28.         //SceneManager.sceneLoaded that it gets called after the scene is loaded?
    29.        
    30.         Debug.Log("Active Scene: " + SceneManager.GetActiveScene().name);
    31.         //this still prints that ManagerScene is active
    32.        
    33.         var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
    34.         go.name = "testCube"; //testcube ends up in ManagerScene, not lvl1
    35.     }
    36.    
    37.     static void InitializeNextScene(Scene old, Scene justActivated)
    38.     {
    39.         Debug.Log(Time.frameCount + "scene activated " + old.name + " " + justActivated.name);
    40.     }
    41.  
    42.     //IEnumerator SetActive(string scene) //this worked fine
    43.     //{
    44.     //    yield return null;
    45.     //    SceneManager.SetActiveScene(SceneManager.GetSceneByName(scene));
    46.     //    Debug.Log("Active Scene: " + SceneManager.GetActiveScene().name);
    47.     //    var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
    48.     //    go.name = "testCube";
    49.     //}
    50. }
    51.  
    Am I using it wrong?
     
  10. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Yes loading != activated
    so you better move object creation to the end of your activation coroutine

    as a proposal to unity team, would be awesome if you would do this coroutine wrapper yourself and give us a callback on when its done.
    like

    SceneManager.ActivateScene(Scene scene, Action<Scene> Callback)
    so that under the hood it does all the activation. just make like "scene activator" that just stores which ones have to be activated and does that next frame, then makes a callback.
     
  11. Orolo

    Orolo

    Joined:
    Dec 5, 2012
    Posts:
    5
    i was trying to activate *after* the scene is loaded. which i thought was supposed to be when it is possible to activate

    what's the point of SceneManager.sceneLoaded if not so i can get notified when the scene is actually done loading?
     
  12. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Even tho you receive onloaded notification you still need to wait one frame before you are allowed to activate the scene.
    What i do for my levels system i have selected "active scene" for a level,
    1. level loads all scenes it contains
    2. level waits one frame
    3. level activates the scene marked as active
     
  13. Orolo

    Orolo

    Joined:
    Dec 5, 2012
    Posts:
    5
    i thought the reason you can't activate the scene right after telling unity to load it is that it takes one from to load. and reacting to SceneManager.sceneLoaded would notify me once it's done loading, so i would then be able to activate.

    if sceneLoaded gets called when the scene starts loading, that seems a bit worthless, since my code caused the load of the new scene anyway, so i'm already "notified", and can just put whatever i would do in response to sceneLoaded right after the call to SceneManager.LoadScene instead. :p
     
  14. Deleted User

    Deleted User

    Guest

    So what is the practical difference between the following 2 scene states, and does isLoaded mean the same thing as the scene being active? When is one state preferred over the other?

    SceneManager.sceneLoaded calls its delegates, but scene.isLoaded == false
    SceneManager.activeSceneChanged calls its delegates, and scene.isLoaded == true
     
  15. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Loaded != active. Only one scene can be active at a time, that scene will be used to sample lighting settings and to instantiate objects in.
    Basically you can think of all the loaded scenes as background and active as foreground.
    Also remember that order is important, and if you load your managers scene after the one that is dependent on managers, it wont be able to locate it (that was true last time i had this issue),
    so i think of scenes as scopes in code, the lower the order of the scene the lower the scope.
    That may have been changed.
     
    Deleted User likes this.
  16. charles01

    charles01

    Joined:
    Mar 28, 2013
    Posts:
    25
    This works, for any one that needs it.

    Code (CSharp):
    1.  
    2.  
    3. void Awake()
    4.         {
    5.  
    6.             SceneManager.activeSceneChanged += OnSceneWasLoaded;
    7.  
    8.         }
    9.  
    10.  
    11.         void OnSceneWasLoaded(Scene result, Scene checkSceneLoaded)
    12.         {
    13.             if (checkSceneLoaded.isLoaded)
    14.             {
    15.                 Debug.Log("OnSceneWasLoaded " + checkSceneLoaded.isLoaded);
    16.             }
    17.             else {
    18.                 Debug.Log("Not OnSceneWasLoaded ");
    19.  
    20.             }
    21.         }
    22.