Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Enter the 2020.2 Beta Sweepstakes for a chance to win an Oculus Quest 2.
    Dismiss Notice

Manually Creating Client and Server Worlds

Discussion in 'Data Oriented Technology Stack' started by drhodor, Dec 16, 2019.

  1. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    39
    I'm using the NetCube NetCodeBootstrap however I've removed the check for the NetCube scene to pass the default world to the base ClientServerBootstrap Initialize. This is because i don't want to have to have everything start in the starting scene. So my Initialize Override looks like how the docs here https://docs.unity3d.com/Packages/com.unity.netcode@0.0/manual/client-server-worlds.html recommend setting up your Initialize as to not create the client and server worlds right away.

    Then, I try creating them from a script in the scene like this:

    Code (CSharp):
    1. ClientServerBootstrap.CreateServerWorld(defaultWorld, "Server World");
    2. ClientServerBootstrap.CreateClientWorld(defaultWorld, "Client World");
    3.  
    After this, I'm using a method in the Game system that does this:

    Code (CSharp):
    1. EntityManager.CreateEntity(typeof(InitGameComponent));
    To start the connection, as per the NetCube example. However nothing happens.

    Adding the InitGameComponent does work when the Initialize passes the default world through to the base Initialize from the NetCodeBootstrap in the scene I am starting with. It just doesn't work if I use the manual creation of client and server worlds as I wrote above. Am confused as to why!
     
  2. TomTales

    TomTales

    Joined:
    Oct 8, 2019
    Posts:
    8
    I found that creating the server and client worlds later on doesn't have the desired effect, because all gameobjects with a ConvertToClientServerEntity component don't convert on Awake, because the server and client world don't exist then. The ConvertToClientServerEntity script has a line of code at the end which is commented out. It's quite useful so just uncomment it:
    UnityEngine.Debug.LogWarning("ConvertEntity failed because there was no Client or Server Worlds", this);

    So all we have to do to make it work, is after creating the worlds (and before spawning the player) convert all objects to clientServerEntities. I did this by taking all the code in the awake function of the ConvertToClientServerEntity script and putting it in a separate public Convert function and then calling that in the awake and when we want to convert it.

    Code (CSharp):
    1. namespace Unity.NetCode
    2. {
    3.     public class ConvertToClientServerEntity : ConvertToEntity
    4.     {
    5.         [Flags]
    6.         public enum ConversionTargetType
    7.         {
    8.             None = 0x0,
    9.             Client = 0x1,
    10.             Server = 0x2,
    11.             ClientAndServer = 0x3
    12.         }
    13.  
    14.         [SerializeField] public ConversionTargetType ConversionTarget = ConversionTargetType.ClientAndServer;
    15.  
    16.         [HideInInspector] public bool canDestroy = false;
    17.  
    18.         void Awake()
    19.         {
    20.             Convert();
    21.         }
    22.  
    23.         public void Convert()
    24.         {
    25.             var system = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<ConvertToEntitySystem>();
    26.  
    27.             bool hasValidTargetWorld = false;
    28.             foreach (var world in World.AllWorlds)
    29.             {
    30.                 bool convertToClient = world.GetExistingSystem<ClientSimulationSystemGroup>() != null;
    31.                 bool convertToServer = world.GetExistingSystem<ServerSimulationSystemGroup>() != null;
    32.  
    33.                 hasValidTargetWorld |= convertToClient || convertToServer;
    34.                 convertToClient &= (ConversionTarget & ConversionTargetType.Client) != 0;
    35.                 convertToServer &= (ConversionTarget & ConversionTargetType.Server) != 0;
    36.  
    37.                 if (convertToClient || convertToServer)
    38.                     system.AddToBeConverted(world, this);
    39.             }
    40.  
    41.             if (!hasValidTargetWorld)
    42.             {
    43.                 UnityEngine.Debug.LogWarning("ConvertEntity failed because there was no Client or Server Worlds", this);
    44.             }
    45.         }
    46.     }
    47. }
    After creating the worlds, go through every gameobject in the scene and if it has the ConvertToClientServerEntity component call Convert() on it:
    Code (CSharp):
    1. #if true
    2.         ClientServerBootstrap.CreateClientWorld(World.DefaultGameObjectInjectionWorld, "Client World");
    3.         ClientServerBootstrap.CreateServerWorld(World.DefaultGameObjectInjectionWorld, "Server World");
    4.  
    5.         GameObject[] allGos = UnityEngine.Object.FindObjectsOfType<GameObject>();
    6.         foreach (GameObject go in allGos)
    7.         {
    8.             if (go.GetComponent<ConvertToClientServerEntity>() != null)
    9.             {
    10.                 go.GetComponent<ConvertToClientServerEntity>().Convert();
    11.                 Debug.Log("converted");
    12.             }
    13.         }
    14. #endif
    I hope this helps you if you're still trying to achieve this. :)
     
    drhodor and shmafoozius like this.
  3. drhodor

    drhodor

    Joined:
    Aug 18, 2013
    Posts:
    39
unityunity