OnLevelWasLoaded() not called at all

I know OnLevelWasLoaded() doesnt work when you load only one scene, since it isnt taken as new scene, but, the problem lies even with loading Scene Additive:

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    void Start()
    {
        SceneManager.LoadScene("Scene_2", LoadSceneMode.Additive);
    }

    void OnLevelWasLoaded(int level)
    {
        Debug.Log("Something loaded");
    }
}

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?

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.

Hey thanks for the upcoming news! Cannot wait for 5.4!

yeeeeeeah. We have to wait another month for literally VITAL thing. I dunno, another spit in the face.

@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.

ooops didnt know about that. :expressionless:

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.

@pointcache it was announced at GDC Unity Blog

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.

Thanks man, this really tickles my fancy. IM PLEASED NOW. :smile:

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:

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

public class LoadLevel : MonoBehaviour {
    public static string currentLevel = "lvl1";
   
    void Awake () {
        SceneManager.sceneLoaded += SceneLoaded;
        SceneManager.activeSceneChanged += InitializeNextScene;
        if (SceneManager.sceneCount < 2)
        {
            SceneManager.LoadScene(currentLevel, LoadSceneMode.Additive);
        }
        //StartCoroutine(SetActive(currentLevel));
    }

    void SceneLoaded(Scene scene, LoadSceneMode m)
    {
        Debug.Log("Scene loaded: " + scene.name + " in mode: " + m); //scene.name is lvl1, as expected
       
        Debug.Log(Time.frameCount + "Active Scene: " + SceneManager.GetActiveScene().name);
        //ManagerScene is active, as expected
       
        SceneManager.SetActiveScene(scene);
        Debug.Log("is scene loaded: " + scene.isLoaded);
        //this prints that scene is *not* loaded; isn't the whole point of
        //SceneManager.sceneLoaded that it gets called after the scene is loaded?
       
        Debug.Log("Active Scene: " + SceneManager.GetActiveScene().name);
        //this still prints that ManagerScene is active
       
        var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
        go.name = "testCube"; //testcube ends up in ManagerScene, not lvl1
    }
   
    static void InitializeNextScene(Scene old, Scene justActivated)
    {
        Debug.Log(Time.frameCount + "scene activated " + old.name + " " + justActivated.name);
    }

    //IEnumerator SetActive(string scene) //this worked fine
    //{
    //    yield return null;
    //    SceneManager.SetActiveScene(SceneManager.GetSceneByName(scene));
    //    Debug.Log("Active Scene: " + SceneManager.GetActiveScene().name);
    //    var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
    //    go.name = "testCube";
    //}
}

Am I using it wrong?

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

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?

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

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. :stuck_out_tongue:

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

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.

1 Like

This works, for any one that needs it.

void Awake()
        {

            SceneManager.activeSceneChanged += OnSceneWasLoaded;

        }


        void OnSceneWasLoaded(Scene result, Scene checkSceneLoaded)
        {
            if (checkSceneLoaded.isLoaded)
            {
                Debug.Log("OnSceneWasLoaded " + checkSceneLoaded.isLoaded);
            }
            else {
                Debug.Log("Not OnSceneWasLoaded ");

            }
        }