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

Multi-scene scenes at startup

Discussion in 'Game Design' started by sdebussc, Oct 9, 2020.

  1. sdebussc

    sdebussc

    Joined:
    Sep 7, 2017
    Posts:
    5
    Problem:
    My game has a startup scene and multiple level scenes. The startup scene is loaded first and (once it has initialized itself) will load a level scene afterwards. The way I prefer to work on levels is to have both the startup and level scene loaded together in the editor (multi-scene editing), but this causes problems if I don't manually remove the level scene before running the game. The game objects in the level scene read from saved game data as they are initialized. I have been searching for a way to prevent the level scene from loading or causing its game objects to destroy themselves, but I haven't found a solution yet.

    Solution 1:
    I tried calling SceneManager.UnloadSceneAsync on the level scene from a script in the startup scene that has the highest priority, but it doesn't get executed quick enough and I still see game objects from the level scene get loaded.

    Solution 2:
    I tried having each game object in the level scene check a global flag in their Awake method and call Destroy on themselves if they should not be created yet. This isn't working very well yet and seems to be the wrong solution as it is very inefficient. I also have to build this into every type of game object that will ever exist in a level scene.

    Question:
    Ideally, I would like to hook into the scene loading mechanism and be able to cancel the loading of a scene before Unity creates all of its game objects and starts calling events on them. Is this possible? If not, what is the recommended approach? This seems like such a basic workflow that I am surprised there is not a better handling for it in Unity.

    Thanks in advance for your help.
     
  2. FabDynamic

    FabDynamic

    Joined:
    Jul 31, 2017
    Posts:
    36
    Good point and question. I've stared at my scenes.cs code for a few minutes and here are my thoughts:

    1. Try adding a script in your level scene and in the awake function call
    SceneManager.LoadScene(0);
    which should interrupt everything quickly and reload just the main scene.

    2. Try adding an event to be invoked at the end of the data load and then all of your classes can register for it in start and have it call back all the stuff they would have done in start otherwise. (A bit about events below)

    3. I know this seems silly at first but a good thing that lots of games (probably most games) have is some kind of scene loading screen, like a curtain which covers up the action behind the scenes until everything is ready and then reveals it all when everything is in good shape.

    Off the top of my head to use events:
    using System;
    and then
    public static event Action MainSceneLoadComplete = delegate {};
    and then call that event when data load is complete and in your level classes have them register in start with something like
    Scenes2.MainSceneLoadComplete += LoadComplete;
    and also in OnDisable
    Scenes2.MainSceneLoadComplete -= LoadComplete;
    and if that doesnt work exactly let me know.


    Good Luck!
     
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,614
    Our game here has a very similar set of requirements. We've solved it by having different code to handle the multi-scene requirements for Editor and play modes.

    For use in the Editor only, every level scene has a "LoadDependencies" script on it. That script loads the required scene(s) and sets the appropriate one to be "active" in the Editor. The result is that everything that's needed is loaded so you can press Play and it all works.

    When the game is running things are actually the other way around. The dependency scene is actually loaded first, because that's what's responsible for running the game and managing state. It then loads whatever other scenes it needs based on that.

    Once all of that was working it made editing stuff nice and convenient. Getting it set up was a bit of a headache, as there were two different code paths that needed to both be implemented and tested. Also, we need to be consciously aware of the differences between the edit-mode and play-mode code to ensure that some things (eg: loading code) work reliably and are tested thoroughly in both cases.

    We just check if a scene is already loaded and, if it is, we don't load it again. There might be some custom logic there to kick off stuff that would otherwise be done when the scene loads, I'm not 100% sure. (I wrote it, but it was quite a while ago now!) There are some things that don't work properly if a scene is loaded "manually" rather than by the game itself, but none of them matter for workflows where we do that.
     
  4. FabDynamic

    FabDynamic

    Joined:
    Jul 31, 2017
    Posts:
    36
    There are a lot of good ideas here. I may do the same where there’s a different code path in the editor.

    how do you deal with objects appearing and doing things before the dependencies are loaded? Something with the start method?