Search Unity

How to retain bootstrap scene on the client?

Discussion in 'Netcode for GameObjects' started by brainwipe, Dec 18, 2022.

  1. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I have a multi-scene project where a player starts a host and clients join.

    A bootstrap scene is the default scene on game load. The bootstrap additively loads the menu scene using normal scene manager. You can do this because the players can only join after the host is running, so they get all the scenes that the host has. I'm not additively creating scenes after the game is running, so I don't need the NetworkManager.LoadScene (I think).

    When the game starts, regarless of host or client, it looks like:
    • Bootstrap
    • Menu
    • DontDestroyOnLoad
    Menu is unloaded as soon as the host or client starts.

    When the host starts, their game looks like:
    • Bootstrap
    • Main
    • DontDestroyOnLoad
    When the client joins, their Bootstrap scene disappears:
    • Main
    • DontDestroyOnLoad
    As the bootstrap scene was loaded when the game was first run, it makes sense that it is spawned before the Network Manager is running (as either host or client). I was expecting to use Scene Validation to protect the existence of the Bootstrap scene but I can't set that up when Bootstrap runs because
    VerifySceneBeforeLoading
    must be set in
    OnNetworkSpawn
    and that's not possible when the host or client haven't started.

    The documentation intimates that bootstrap scene types are possible but I'm bereft of good examples.

    I feel like I'm missing something obvious, here! I can't be the only one with multiple additive scenes. Thanks in advance.
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    Is the NetworkManager object in the bootstrap scene? It will have to be in that scene since the host is running it.

    So this isn't actually the bootstrap scene you're using, it's the GameScene because you're running the game in it. ;)

    Try doing the following setup:

    • BootstrapScene => contains NetworkManager object and only loads the GameScene (not additive!)
    • GameScene (formerly known as Bootstrap) => additively loads the menu scene
    After game commences the scene should look like this on all machines:
    • GameScene
    • Main
    • DontDestroyOnLoad
    This best reflects normal mode of operations anyway, since games usually have to tell you upon startup that they have an uncanny valley intro video they spent way too much money on which they got after Nvidia decided to sponsor the game because it uses three or more raycasts overall and of course you'll have the ubiquitious "don't flamethrower your computer while this icon appears" and lastly, several minutes of logo-animated loading screen that only takes so long due to the logo animation loading because junior dev was tasked with this so he couldn't possibly break the game. :cool:

    PS: when loading the GameScene make sure to do so in one of the later events like Update because Awake and possibly OnEnable and/or Start (can't remember) will be too early to load a new scene, causing either an error or even freeze/crash.
     
    Last edited: Dec 18, 2022
  3. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    Brilliant, thank you @CodeSmile. Adding another level of direction should do it. I'll report back when I have it working.
     
  4. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I'm afraid that doesn't seem to work.

    The new bootstrap has the NetworkManager and a new script that does one thing - load the Game scene. If I use SceneManager.LoadScene:

    Code (CSharp):
    1. public class Bootstrap : MonoBehaviour
    2.     {
    3.         private void Update()
    4.         {
    5.             SceneManager.LoadScene("Game", LoadSceneMode.Single);
    6.         }
    7.     }
    Then the Network Scene Manager on the client will remove the Game scene as soon as it connects. If I change it to:

    Code (CSharp):
    1. public class Bootstrap : MonoBehaviour
    2.     {
    3.         private void Update()
    4.         {
    5.             NetworkManager.Singleton.SceneManager.LoadScene("Game", LoadSceneMode.Single);
    6.         }
    7.     }
    Then you will get an error because the SceneManager is only available when the host or client has started.

    Any thoughts on that?
     
  5. TruckerJoe

    TruckerJoe

    Joined:
    Feb 25, 2019
    Posts:
    39
    You have to start the host before you use the NetworkManager.Singleton.SceneManger.
    I start the host when the host in my lobby starts the game, and then I use NetworkManager.Singleton.SceneManger.
    The Scene change is working, but the host player is spawned then in the lobby scene.
    That is my problem :(
     
  6. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
  7. Quest_for_stuff

    Quest_for_stuff

    Joined:
    Nov 11, 2014
    Posts:
    11
    I'm literally having the exact same problem. I'm not sure how to approach it did you found a solution @brainwipe ?
     
  8. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    258
    @Quest_for_stuff
    You might take a look at this thread and leverage from the NetworkSceneManager's additive client synchronization mode:

    The general idea is that as opposed to the client unloading and then reloading the same scenes when in the default single client synchronization mode (and potentially unloading scenes you want to keep loaded), it will just use any scenes that are already loaded on the client side to synchronize with any scenes the server tells the client to load during the initial synchronization.

    The default post synchronization action is for clients to leave any scenes that were loaded alone (i.e. they remain loaded). If you want to change this behavior such that the clients only keep the scenes used for synchronization loaded, then you can set the NetworkSceneManager.PostSynchronizationSceneUnloading to true and the client will automatically unload any scenes not used during synchronization (when it is done synchronizing).
     
    brainwipe likes this.