Search Unity

Question Shutting down a Server

Discussion in 'NetCode for ECS' started by SchnozzleCat, Jul 6, 2021.

  1. SchnozzleCat

    SchnozzleCat

    Joined:
    Oct 23, 2013
    Posts:
    42
    What is the intended way to "shut down" a server?

    I currently add a NetworkStreamRequestDisconnect to all NetworkStreamConnections, and then wait until no more NetworkStreamConnections exist (this also destroys the NetworkStreamConnections on the client). This does not however turn off listening on the server, which means clients can still connect. I didn't find anything about stopping listening, so I added the following to NetworkStreamReceiveSystem, based on that system's OnDestroy function.

    Code (CSharp):
    1.  
    2. public void StopListening()
    3. {
    4.     if (World.GetExistingSystem<ServerSimulationSystemGroup>() == null || !m_DriverListening) return;
    5.  
    6.     using (var networkStreamConnections = m_NetworkStreamConnectionQuery.ToComponentDataArray<NetworkStreamConnection>(Allocator.TempJob))
    7.     {
    8.         foreach (var connection in networkStreamConnections)
    9.         {
    10.             m_Driver.Disconnect(connection.Value);
    11.         }
    12.     }
    13.     m_Driver.Dispose();
    14.  
    15.     DriverConstructor.CreateServerDriver(World, out m_Driver, out m_UnreliablePipeline, out m_ReliablePipeline, out m_UnreliableFragmentedPipeline);
    16.  
    17.     m_ConcurrentDriver = m_Driver.ToConcurrent();
    18.     m_DriverListening = false;
    19. }
    20.  
    This seems to work, at least I am not getting any errors in my short testing, and after calling StopListening() the client will not be able to connect until Listen() is called again on the NetworkStreamReceiveSystem.

    Is this a good way to do it? Or is there some better public facing API to do this? That would be nice as currently I need to modify the package since a lot of the members in my StopListening function are private / internal.

    Any help is as always appreciated! :)
     
  2. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    No, there is no available api to make the driver stop listening at the moment.

    Disconnecting the connection like that is not completely correct since it does not destroy the network stream connection entities. Also, you may wants to reset the freeNetworkIds queue, numNetworkId as well.

    The ideal workflow to shutdown the server is indeed to disconnect al the connection (like you did, no need to wait) and the dispose the whole server world.
    If you need to restart a server, just re-create the ServerWorld using the ClientServerBootstrap.CreteServerWorld method.
    This give you the guarantee that also the state of the world is what you expect and no leftover entities are present.

    Of course that may depend on the use case on hand.
     
  3. SchnozzleCat

    SchnozzleCat

    Joined:
    Oct 23, 2013
    Posts:
    42
    That seems like a much cleaner and simpler way to do it, I never thought of it. Also loving the fact that this guarantees "state reset", which is exactly what I wanted. Thanks!

    Edit:
    One small issue I ran into:

    If I dispose of the server world and create a new one with ClientServerBootstrap.CreateServerWorld, the ghost collection system is missing. I assume this is because the subscene conversion only runs once.

    My workaround for now is as follows:

    Code (CSharp):
    1.  
    2. //Add subscenes to newly created world
    3. GameObject.FindObjectsOfType<SubScene>().ForEach((x) =>
    4. {
    5.     var sceneSystem = serverWorld.GetExistingSystem<SceneSystem>();
    6.     if (sceneSystem != null)
    7.     {
    8.         var loadParams = new SceneSystem.LoadParameters
    9.         {
    10.             Flags = SceneLoadFlags.DisableAutoLoad
    11.         };
    12.  
    13.         var sceneEntity = sceneSystem.LoadSceneAsync(x.SceneGUID, loadParams);
    14.         sceneSystem.EntityManager.AddComponentObject(sceneEntity, x);
    15.     }
    16. });
     
    Last edited: Jul 6, 2021
  4. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    900
    The problem is not the conversion. The scene are converted at authoring time (apart if you have the SubScene opened).
    The issue is that when you enter playmode the SubScene marked as AutoLoad are automatically loaded by the SceneSystem (the SubScene OnAwake() just load them in all worlds).
    If you dispose the ServerWorld, then is your responsibility to reload them.

    Your work around should work ok in the Editor and in hybrid builds. It would not work if you target to use DOTS Server / DOTS Runtime (there is not support for GameObject and UnityEngine stuff).

    Another solution (that may be appealing or not but make the flow always the same) is to let the Server and the Client always load the subscenes they needs (you should have some system that do that). So all the SubScenes should have the AutoLoad flag set to false.
    How to retrieve/store the scene set you want to load is up to you, There are different approaches for that.
     
  5. SchnozzleCat

    SchnozzleCat

    Joined:
    Oct 23, 2013
    Posts:
    42
    I don't plan to build to a DOTS exclusive environment (my project uses a lot of scriptable objects at runtime), but I'll keep that in mind. Thanks!
     
  6. Ali_Bakkal

    Ali_Bakkal

    Joined:
    Jan 26, 2013
    Posts:
    90
    Hello, my question is related to this topic :
    I have a MenuScene and InGameScene.
    Inside of the MenuScene, I have all the UI.
    Inside of the InGameScene, i have all the Netcode Package and ECS for the game.

    When I am inside the MenuScene and launch the game (So i move from MenuScene to InGameScene), the game is working perfectly, very smooth (because it is the first time i launch the game). After the game ends, i am getting back to MenuScene.
    Here is the problem : if i launch another game when i go the InGameScene, i have a lots of error.. and the game is not properly launched..

    What should i do to go back and forth between the two scenes with a fresh launch of Netcode, each time i launch the InGameScene ?

    Thanks in advance, @CMarastoni @timjohansson
    Ali