|
| 1 | +# Client server Worlds |
| 2 | + |
| 3 | +NetCode has a separation of client and server logic, and both the client and server logic are in separate Worlds (the client World, and the server World), based on the [hierarchical update system](https://docs.unity3d.com/Packages/com.unity.entities@latest/index.html?subfolder=/manual/system_update_order.html) of Unity’s Entity Component System (ECS). |
| 4 | + |
| 5 | +By default, NetCode places systems in both client and server Worlds, but not in the default World. |
| 6 | +> [!NOTE] |
| 7 | +> Systems that update in the `PresentationSystemGroup` are only added to the client World. |
| 8 | +
|
| 9 | +To override this default behavior, use the [UpdateInWorld](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.UpdateInWorld.html) attribute, or the `UpdateInGroup` attribute with an explicit client or server system group. The available explicit client server groups are as follows: |
| 10 | + |
| 11 | +* [ClientInitializationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientInitializationSystemGroup.html) |
| 12 | +* [ServerInitializationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ServerInitializationSystemGroup.html) |
| 13 | +* [ClientAndServerInitializationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientAndServerInitializationSystemGroup.html) |
| 14 | +* [ClientSimulationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientSimulationSystemGroup.html) |
| 15 | +* [ServerSimulationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ServerSimulationSystemGroup.html) |
| 16 | +* [ClientAndServerSimulationSystemGroup ](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientAndServerSimulationSystemGroup.html) |
| 17 | +* [ClientPresentationSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientPresentationSystemGroup.html) |
| 18 | + |
| 19 | +> [!NOTE] |
| 20 | +> There is no server presentation system group. |
| 21 | +
|
| 22 | +As well as the attributes listed above, you can use the __PlayMode Tools__ window in the Unity Editor to select what happens when you enter Play Mode. To access __PlayMode Tools__, go to menu: __Multiplayer > PlayMode Tools__. |
| 23 | + |
| 24 | +<br/>_PlayMode Tools_ |
| 25 | + |
| 26 | +|**Property**|**Description**| |
| 27 | +|:---|:---| |
| 28 | +|__PlayMode Type__|Choose to make Play Mode either __Client__ only, __Server__ only, or __Client & Server__.| |
| 29 | +|__Num Thin Clients__|Set the number of thin clients. Thin clients cannot be presented, and never spawn any entities it receives from the server. However, they can generate fake input to send to the server to simulate a realistic load.| |
| 30 | +|__Client send/recv delay__|Use this property to emulate high ping. Specify a time (in ms) to delay each outgoing and incoming network packet by. | |
| 31 | +|__Client send/recv jitter__|Use this property to add a random value to the delay, which makes the delay a value between the delay you have set plus or minus the jitter value. For example, if you set __Client send/recv delay__ to 45 and __Client send/recv jitter__ to 5, you will get a random value between 40 and 50.| |
| 32 | +|__Client package drop__|Use this property to simulate bad connections where not all packets arrive. Specify a value (as a percentage) and NetCode discards that percentage of packets from the total it receives. For example, set the value to 5 and NetCode discards 5% of all incoming and outgoing packets.| |
| 33 | +|__Client auto connect address (Client only)__|Specify which server a client should connect to. This field only appears if you set __PlayMode Type__ to __Client__. The user code needs to read this value and connect because the connection flows are in user code. | |
| 34 | + |
| 35 | +When you enter Play Mode, from this window you can also disconnect clients and choose which client Unity should present if there are multiple. When you change a client that Unity is presenting, it stops calling the update on the `ClientPresentationSystemGroup` for the Worlds which it should no longer present. As such, your code needs to be able to handle this situation, or your presentation code won’t run and all rendering objects you’ve created still exist. |
| 36 | + |
| 37 | +## Bootstrap |
| 38 | + |
| 39 | +The default bootstrap creates client server Worlds automatically at startup. It populates them with the systems defined in the attributes you have set. This is useful when you are working in the Editor, but in a standalone game, you might want to delay the World creation so you can use the same executable as both a client and server. |
| 40 | + |
| 41 | +To do this, you can create a class that extends `ClientServerBootstrap` to override the default bootstrap. Implement `Initialize` and create the default World. To create the client and server worlds manually, call `ClientServerBootstrap.CreateClientWorld(defaultWorld, "WorldName");` or `ClientServerBootstrap.CreateServerWorld(defaultWorld, "WorldName");`. |
| 42 | + |
| 43 | +The following code example shows how to override the default bootstrap to prevent automatic creation of the client server worlds: |
| 44 | + |
| 45 | +```c# |
| 46 | +public class ExampleBootstrap : ClientServerBootstrap |
| 47 | +{ |
| 48 | + public override bool Initialize(string defaultWorldName) |
| 49 | + { |
| 50 | + var systems = DefaultWorldInitialization.GetAllSystems(WorldSystemFilterFlags.Default); |
| 51 | + GenerateSystemLists(systems); |
| 52 | + |
| 53 | + var world = new World(defaultWorldName); |
| 54 | + World.DefaultGameObjectInjectionWorld = world; |
| 55 | + |
| 56 | + DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(world, ExplicitDefaultWorldSystems); |
| 57 | + ScriptBehaviourUpdateOrder.UpdatePlayerLoop(world); |
| 58 | + return true; |
| 59 | + } |
| 60 | + |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +## Fixed and dynamic timestep |
| 65 | + |
| 66 | +When you use NetCode, the server always updates at a fixed timestep. NetCode limits the maximum number of iterations to make sure that the server does not end up in a state where it takes several seconds to simulate a single frame. |
| 67 | + |
| 68 | +The fixed update does not use the [standard Unity update frequency](https://docs.unity3d.com/Manual/class-TimeManager.html). A singleton entity in the server World controls the update with a [ClientServerTickRate](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.ClientServerTickRate.html) component. The `ClientServerTickRate` controls `SimulationTickRate` which sets the number of simulation ticks per second. |
| 69 | + |
| 70 | +> [!NOTE] |
| 71 | +> `SimulationTickRate` must be divisible by `NetworkTickRate`. |
| 72 | +
|
| 73 | +The default number of simulation ticks is 60. The component also has values for MaxSimulationStepsPerFrame which controls how many simulations the server can run in a single frame, and TargetFrameRateMode which controls how the server should keep the tick rate. Available values are: |
| 74 | + |
| 75 | +* `BusyWait` to run at maximum speed |
| 76 | +* `Sleep` for `Application.TargetFrameRate` to reduce CPU load |
| 77 | +* `Auto` to use `Sleep` on headless servers and `BusyWait` otherwise |
| 78 | + |
| 79 | +The client updates at a dynamic time step, with the exception of prediction code which always runs at a fixed time step to match the server. The prediction runs in the [GhostPredictionSystemGroup](https://docs.unity3d.com/Packages/com.unity.netcode@latest/index.html?subfolder=/api/Unity.NetCode.GhostPredictionSystemGroup.html) and applies its own fixed time step for prediction. |
| 80 | + |
| 81 | +## Standalone builds |
| 82 | + |
| 83 | +When you build a standalone game, NetCode uses the __Server Build__ property in the __Build Settings__ window to decide what to build. If the property is enabled, NetCode sets the ```UNITY_SERVER``` define and you get a server-only build. If the property is disabled you get a combined client and server build. You can use a combined client and server build to decide if a game should be client, server or both at runtime. |
| 84 | + |
| 85 | +To build a client-only game, add the ```UNITY_CLIENT``` define to the __Scripting Define Symbols__ in the __Player Settings__ (menu: __Edit > Project Settings > Player > Configuration__). You can have the ```UNITY_CLIENT``` define set when you build a server, but the ```UNITY_SERVER``` define takes precedence and you get a server-only build. |
0 commit comments