Search Unity

Question Load the Game Scene when everybody's ready

Discussion in 'Netcode for GameObjects' started by GuirieSanchez, Nov 8, 2022.

  1. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    So, I would like to ask for a way to wait for all clients to be connected and ready before calling
    NetworkManager.Singleton.SceneManager.LoadScene(gameSceneName, LoadSceneMode.Single);
    .

    Also, and most importantly, I would appreciate it if someone could elaborate on a way to wait for everybody to be done loading a scene so that all clients and the host start the scene at the very same time (since I'm still new to netcode/network, I would very much appreciate a working example).

    Having the clients not loading the scene at the same time can cause a lot of issues. For instance, because I have [ClientRpc]s on certain scene objects, when a client that loads the scene earlier than the rest fires an update or an RPC function at the same time as some other client connects, then it breaks the game because the script that contains the RPC in that client's scene is not done yet referencing its components.
     
  2. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    I appreciate any help.

    I tried to use the "SceneEventType" callbacks found in the documentation (here) to no avail.

    Things of this sort (below)
    Code (CSharp):
    1. private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
    2.     {
    3.         var clientOrServer = sceneEvent.ClientId == NetworkManager.ServerClientId ? "server" : "client";
    4.         switch (sceneEvent.SceneEventType)
    5.         {
    6.             case SceneEventType.LoadComplete:
    7.                 {
    8.                     // We want to handle this for only the server-side
    9.                     if (sceneEvent.ClientId == NetworkManager.ServerClientId)
    10.                     {
    11.                         // *** IMPORTANT ***
    12.                         // Keep track of the loaded scene, you need this to unload it
    13.                         m_LoadedScene = sceneEvent.Scene;
    14.                     }
    15.                     Debug.Log($"Loaded the {sceneEvent.SceneName} scene on " +
    16.                         $"{clientOrServer}-({sceneEvent.ClientId}).");
    17.                     break;
    18.                 }
    19.             case SceneEventType.UnloadComplete:
    20.                 {
    21.                     Debug.Log($"Unloaded the {sceneEvent.SceneName} scene on " +
    22.                         $"{clientOrServer}-({sceneEvent.ClientId}).");
    23.                     break;
    24.                 }
    25.             case SceneEventType.LoadEventCompleted:
    26.             case SceneEventType.UnloadEventCompleted:
    27.                 {
    28.                     var loadUnload = sceneEvent.SceneEventType == SceneEventType.LoadEventCompleted ? "Load" : "Unload";
    29.                     Debug.Log($"{loadUnload} event completed for the following client " +
    30.                         $"identifiers:({sceneEvent.ClientsThatCompleted})");
    31.                     if (sceneEvent.ClientsThatTimedOut.Count > 0)
    32.                     {
    33.                         Debug.LogWarning($"{loadUnload} event timed out for the following client " +
    34.                             $"identifiers:({sceneEvent.ClientsThatTimedOut})");
    35.                     }
    36.                     break;
    37.                 }
    38.         }
    39.     }
     
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    When you get the „scene completed loading“ event on a client you send a ServerRpc telling the server „i‘m ready“ and when the server received that for every connected client (also check timed out clients) then they are all ready and the server can start the game by sending a ClientRpc.
     
  4. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    This is clever! thanks for the tip.

    I did it with a
    [ServerRpc(RequireOwnership = false)]
    , since this is a client calling a ServerRpc, or else I'll get an error.

    A question that I have now regarding this method is: is there a way for the server to know how many clients are registering for the game? So that it waits for all of them before calling the ClientRpc?

    In the game in question, there are modes from 2 players up to 9 players. Imagine I set the mode to 6 players max. Is there a way to track how many clients are connecting to the server and assign them a reference so that I can keep track of them? This way, I could make a bool that says: if all the referenced clients are done loading, then call the ClientRpc.


    PS:
    how could this be done?
     
  5. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    Usually that requires a Lobby scene where players meet up on a specific server, and every client has a button to toggle its "ready" state. The game commences by loading some other scene when all players are "ready". I have made an example here: https://github.com/CodeSmile-000001...Plugins/CodeSmile/Netcode/QuickStart/04_Lobby

    This way, you know how many players will be in the game session.
    Use NetworkManager.ConnectedClientList (recalled from memory) to get the players and their count.

    It's in the script you posted. ;)
    Code (CSharp):
    1. if (sceneEvent.ClientsThatTimedOut.Count > 0)
     
    GuirieSanchez likes this.
  6. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452

    Thank you so much! I had to reinstall the Netcode package for it to work, maybe it was outdated. Also, I couldn't manage to get the syncParrel package, so I'll be testing it without it (maybe it's still workable).

    As soon as I come back home I'll dive into the different features that it's got, such as limiting the number of clients, etc. It looks super useful, thank you for sharing!
     
  7. GuirieSanchez

    GuirieSanchez

    Joined:
    Oct 12, 2021
    Posts:
    452
    Hi @CodeSmile, I have a quick question regarding your setup. What are the "host again" and "server again" buttons for?

    I imagine that the "join again" button will reconnect a disconnected client without having to re-enter the password again if he wants to connect back to the same server. But if a host gets disconnected, won't the server shut down automatically?