Search Unity

Resolved Wait for a "Network.Singleton.Scene" to be fully loaded. Help!!

Discussion in 'Multiplayer' started by GuirieSanchez, Nov 6, 2022.

  1. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    Hi everyone!

    I want to wait for a scene to be fully loaded before executing some code. For a regular Scene Manager you could just use the async operation:
    Code (CSharp):
    1. private IEnumerator WaitForSceneToLoad()
    2.     {
    3.         var asyncLoadLevel = SceneManager.LoadSceneAsync(gameSceneName, LoadSceneMode.Single);
    4.         while (!asyncLoadLevel.isDone)
    5.         {
    6.             Debug.Log("Loading Scene");
    7.             yield return null;
    8.         }
    9.         //Do whatever
    10. }
    However, there's no equivalent for a
    Network.Singleton.SceneManager
    . The following piece of code will not work:
    Code (CSharp):
    1. private IEnumerator WaitForSceneToLoad()
    2.     {
    3.         var asyncLoadLevel = NetworkManager.Singleton.SceneManager.LoadScene(gameSceneName, LoadSceneMode.Single);
    4.         while (!asyncLoadLevel.isDone) //Here's the problem, there's no "isDone" for network
    5.         {
    6.             Debug.Log("Loading Scene");
    7.             yield return null;
    8.         }
    9.        //Do whatever
    10.  
    11.     }
    Is there an alternative to check if a scene loaded through the NetworkManager is completed?
     
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    If this is for Netcode for GameObjects take a look at the NetworkManager.Singleton.SceneManager.On* callbacks, sounds like you want OnLoadComplete or OnLoadEventCompleted.
     
    CodeSmile and GuirieSanchez like this.
  3. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    Thank you. Indeed, a callback is even better than I expected. I saw in the documentation that in order to use it you have to implement the
    public delegate void OnLoadCompleteDelegateHandler(ulong clientId, string sceneName, LoadSceneMode loadSceneMode);


    Apart from this, I have no idea how this callback works though. Could you please give me an example of it?
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    The way it works is you pass a function to subscribe to a particular event, when that event occurs the function is called. This is more efficient than continuously polling to check if that event has happened.

    Here's a simple example,
    Code (CSharp):
    1.     // subscribe to OnLoadComplete event
    2.     NetworkManager.Singleton.SceneManager.OnLoadComplete += OnLoadComplete;
    3.     .
    4.     .
    5.     .
    6.     // called when scene load complete
    7.     private void OnLoadComplete(ulong clientId, string sceneName, LoadSceneMode loadSceneMode)
    8.     {
    9.         Debug.Log("OnLoadComplete clientId: " + clientId + " scene: " + sceneName + " mode: " + loadSceneMode);
    10.     }
     
    GuirieSanchez likes this.
  5. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    Thank you!

    I imagine the OnLoadComplete function will trigger for any scene that is fully loaded. Is there a way to specify a scene for it to work?
     
  6. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    Outside of filtering on sceneName I'm not sure, I don't use the scene callbacks as I do my own scene management. What I do have is a test project that subscribes to all callbacks, it's handy for testing anything network related and I would recommend setting up a test project yourself.
     
    GuirieSanchez likes this.
  7. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    I'm getting this error

    upload_2022-11-7_22-45-42.png
     
  8. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    If you want to take an action on an event, like make an ServerRpc call, you need to put that inside your event callback function:

    Code (CSharp):
    1.    private void OnLoadComplete(ulong clientId, string sceneName, LoadSceneMode loadSceneMode)
    2.     {
    3.         Debug.Log("OnLoadComplete clientId: " + clientId + " scene: " + sceneName + " mode: " + loadSceneMode);
    4.  
    5.         SpawnGameManagerServerRpc();
    6.     }
    As it stands OnLoadComplete is going to be called on loading a scene on each client, in case you only want to spawn the game manager once.
     
  9. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    upload_2022-11-8_0-26-8.png

    I think I'm missing some code that allows this to work.

    It reminds me of Input Callbacks, for "PointerClick" for example, where you have to put this at the top of the script:

    E.g.:
    Code (CSharp):
    1. public class Example : MonoBehaviour, IPointerClickHandler //this bad boy right here
     
  10. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    You don't want the brackets on += OnLoadComplete() as you're referencing it rather than calling it.
    Code (CSharp):
    1. NetworkManager.Singleton.SceneManager.OnLoadComplete += OnLoadComplete;
     
    GuirieSanchez likes this.
  11. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    I'm a complete moron. That did the trick. Thank you!