Instantiating objects only after scene has been loaded

I’m trying to spawn in objects into the scene from a save file. All the logic is done through my “GameManager” script which is a singleton and persists across both scenes. When transitioning from my main menu to the main level, I call SceneManager.LoadScene("main_level");

However, this totally screws up my entire saving and loading methods.

public void LoadGame()
    {
        SceneManager.LoadScene("main_level");
        string jsonData;
        if (newGame) // Start new game
        {
            var defaultPath = Application.streamingAssetsPath + "/Default/Default.json";
            if (File.Exists(defaultPath))
            {
                jsonData = File.ReadAllText(defaultPath);
                gameData = JsonUtility.FromJson<GameData>(jsonData);
            }
            else
            {
                Debug.LogError("Save file is missing at: " + defaultPath);
            }
        }
        else if (File.Exists(path + "/" + saveName))
        {
            jsonData = File.ReadAllText(path + "/" + saveName);
            gameData = JsonUtility.FromJson<GameData>(jsonData);
        }
        else
        {
            Debug.LogError("Save file is missing at: " + path + "/" + saveName);
        }

        /* Instantiate required objects */

        // Trees
        var treeParent = new GameObject("Trees");
        foreach (TreeSaveLoad.TreeData tree in gameData.trees)
        {
            var treeType = oakTree;
            switch (tree.type)
            {
                case (TreeSaveLoad.TreeType.Redwood):
                    treeType = redwoodTree;
                    break;
                case (TreeSaveLoad.TreeType.Birch):
                    treeType = birchTree;
                    break;
                case (TreeSaveLoad.TreeType.Beech):
                    treeType = beechTree;
                    break;
                case (TreeSaveLoad.TreeType.Pine):
                    treeType = pineTree;
                    break;
                case (TreeSaveLoad.TreeType.Oak):
                    treeType = oakTree;
                    break;
                case (TreeSaveLoad.TreeType.Maple):
                    treeType = mapleTree;
                    break;
                default:
                    Debug.LogError("Missing tree type.");
                    break;
            }
            var treeChild = Instantiate(treeType, tree.position, Quaternion.identity) as Transform;
            treeChild.SetParent(treeParent.transform, true);
            yield return null;
        }

        // Call load event
        if (EventManager.Instance.e_loadGame != null)
        {
            EventManager.Instance.e_loadGame.Invoke();
        }

        // Call last, after loading is finished
        if (EventManager.Instance.e_loadedGame != null)
        {
            EventManager.Instance.e_loadedGame.Invoke();
        }

I’m trying to spawn my trees from a save file, as well as call a few Unity events that will handle other loading methods. However, what I’m seeing is that the scene loads AFTER my loading methods are called, resetting the entire scene and throwing a whole bunch of errors. How do I ensure that I can move across scenes and only begin to instantiate objects after the scene has been loaded?

You’ll need to subscribe to the sceneLoaded event.

As per the docs: “When using SceneManager.LoadScene, the loading does not happen immediately, it completes in the next frame. This semi-asynchronous behavior can cause frame stuttering and can be confusing because load does not complete immediately.”

Hook into the sceneLoaded event and call your loading code there.