Struct ClientServerTickRate
The ClientServerTickRate singleton is used to configure the client and server simulation time step, server packet send rate and other related settings. The singleton entity is automatically created for the clients in the NetworkStreamReceiveSystem first update if not present. On the server, by contrast, the entity is never automatically created and it is up to the user to create the singletong instance if they need to. This behaviour is asymmetric because the client need to have this singleton data synced with the server one. It is like this for compatibility reason and It may be changed in the future. In order to configure these settings you can either:
- Create the entity in a custom ClientServerBootstrap after the worlds has been created.
- On a system, in either the OnCreate or OnUpdate.
- the maximum number of tick per frame
- the maximum number of tick per frame
- tick batching (<`MaxSimulationStepBatchSize`) and others.
Implements
Inherited Members
Namespace: Unity.NetCode
Assembly: Unity.NetCode.dll
Syntax
[Serializable]
public struct ClientServerTickRate : IComponentData, IQueryTypeParameter
Remarks
- Once the client is connected, changes to the ClientServerTickRate are not replicated. If you change the settings are runtime, the same change must be done on both client and server.
- The ClientServerTickRate should never be added to sub-scene with a baker. In case you want to setup the ClientServerTickRate based on some scene settings, we suggest to implement your own component and change the ClientServerTickRate inside a system in your game.
Examples
class MyCustomClientServerBootstrap : ClientServerBootstrap
{
override public void Initialize(string defaultWorld)
{
base.Initialise(defaultWorld);
var customTickRate = new ClientServerTickRate();
//run at 30hz
customTickRate.simulationTickRate = 30;
customTickRate.ResolveDefault();
foreach(var world in World.All)
{
if(world.IsServer())
{
//In this case we only create on the server, but we can do the same also for the client world
var tickRateEntity = world.EntityManager.CreateSingleton(new ClientServerTickRate
{
SimulationTickRate = 30;
});
}
}
}
}
Fields
HandshakeApprovalTimeoutMS
The timeout for the connection handshake and approval procedure.
Note: This is one counter for both states. In other words: The client must complete both Handshake
and Approval before this timeout expires - it's not reset upon entering Approval.
As soon as the client is accepted on the server, the timer will start.
Timeout will occur if the server has not handshaked and approved the connection
within the given duration. The default is 5000ms.
Declaration
[Tooltip("The timeout for the connection handshake and approval procedure. Both must succeed within the allotted time!\n\nDefaults to 0ms (which becomes 5s).")]
[Range(0, 120000)]
public uint HandshakeApprovalTimeoutMS
Field Value
Type | Description |
---|---|
uint |
Remarks
The overall timeout sequence when a client is connecting is:
1. The client goes through the transport-level connection timeout first (max connect attempt * connect timeout).
2. Then, once the UTP connection succeeds, netcode begins the handshake process, where protocol
version RPCs are automatically exchanged.
3. If the client protocol is valid, the server will move the client to either the connected state,
or to the approval state (if approval is enabled via RequireConnectionApproval).
This timeout applies to both the Handshake and Approval elapsed durations. It's a single timer for both.
MaxSimulationStepBatchSize
If the server cannot keep up with the simulation frequency with running MaxSimulationStepsPerFrame
ticks, it is possible to allow each tick to run with a longer delta time in order to keep the game
time updating correctly. This means that instead of running two ticks with delta time N each, the
system will run a single tick with delta time 2*N. It is a less expensive but more inaccurate way
of dealing with server performance spikes, it also requires the game logic to be able to handle it.
Declaration
[Tooltip("Denotes how many individual ticks will be batched together (into a single tick) when recovering from a severe slowdown.\n\nDefault value is 0 (which becomes 4).\n\n<b>Warning: You lose accuracy when batching ticks, and gameplay code must account for it.</b>")]
[Range(0, 16)]
public int MaxSimulationStepBatchSize
Field Value
Type | Description |
---|---|
int |
MaxSimulationStepsPerFrame
If the server cannot keep up with the passing of realtime (i.e. the server is ticking at too low a rate to match the SimulationTickRate), it will perform multiple ticks in a single frame (in an attempt to 'catch up'). This setting puts a limit on how many such updates it can perform in a single frame. Once this limit is reached, the simulation time will update slower than real time. The default value is 1.
Declaration
[Tooltip("Denotes how many fixed-step ticks can be performed on any given Unity frame, when 'catching up', when running too slowly.\n\nDefault value is 0 (which becomes 1).")]
[Range(0, 16)]
public int MaxSimulationStepsPerFrame
Field Value
Type | Description |
---|---|
int |
Remarks
The network tick rate only applies to snapshots, the frequency commands and RPCs is not affected by this setting.
NetworkTickRate
The rate at which the server creates (and sends) a snapshots to each client. This can be lower than than the simulation frequency, which means the server only sends new snapshots to the clients every N frames. Defaults to the SimulationTickRate.
Declaration
[Tooltip("The rate at which the server creates (and sends) a snapshot to each client.\n\nIf zero (the default), this value will be set to the <b>SimulationTickRate</b>, but half (or one third) is often good enough.\n\nThe CPU work performed to build and send snapshots is often the most significant CPU cost in a multiplayer game. Thus, reducing this send-rate can lead to significant CPU savings, but at the expense of gameplay quality (especially when packets are lost to the network).")]
[Min(0)]
public int NetworkTickRate
Field Value
Type | Description |
---|---|
int |
Remarks
The CPU work performed to build and send snapshots (via GhostSendSystem) is often the most significant CPU cost in a multiplayer game. Thus, reducing this send-rate can lead to significant CPU savings, but at the expense of gameplay quality (especially when packets are lost to the network). Note that the server can still send data on every simulation tick, but to different subsets of clients. This is to distribute CPU load over multiple simulation ticks (to avoid CPU spikes). For example, with a NetworkTickRate of 30 and a SimulationTickRate of 60, the server will send snapshots to half of the clients for one tick, and the other half, the next tick. So each client still end up with a packet every 2 simulation ticks, while the server is distributing the CPU load over each tick (via a 'round robin' strategy).
PredictedFixedStepSimulationTickRatio
Multiplier used to calculate the tick rate (i.e. frequency) for the PredictedFixedStepSimulationSystemGroup. The group rate must be an integer multiple of the SimulationTickRate. The default value is 1, meaning that the PredictedFixedStepSimulationSystemGroup run at the same frequency as the prediction loop. The calculated delta is 1.0/(SimulationTickRate*PredictedFixedStepSimulationTickRatio).
Declaration
[Tooltip("Multiplier used to calculate the tick rate (i.e. frequency) for the PredictedFixedStepSimulationSystemGroup.\n\nThe default (and recommendation) is 0 (which becomes 1 i.e. one fixed step per tick), where higher values allow physics to tick more frequently (i.e. at smaller intervals).")]
[Range(0, 8)]
public int PredictedFixedStepSimulationTickRatio
Field Value
Type | Description |
---|---|
int |
SimulationTickRate
The fixed simulation frequency on the server and prediction loop. The client can render at a higher or lower rate than this. Default: 60Hz.
Declaration
[Tooltip("The fixed simulation frequency of the Netcode gameplay simulation. Higher values incur higher CPU costs on both the client and server, especially during client prediction.")]
[Min(1)]
public int SimulationTickRate
Field Value
Type | Description |
---|---|
int |
Remarks
Note: Clients are not locked to this refresh rate (see Partial Ticks documentation). Higher values increase gameplay quality, but incur higher CPU and bandwidth costs. Higher values are particularly expensive on the client, as prediction cost increases.
TargetFrameRateMode
If the server is capable of updating more often than the simulation tick rate, it can either
skip the simulation tick for some updates (BusyWait
), or limit the updates using
Application.TargetFrameRate
(Sleep
). Auto
makes it use Sleep
for dedicated server
builds and BusyWait
for client and server builds (as well as the editor).
Declaration
[Tooltip("Denotes how the server should sleep, when determining when it should next tick.\n\nDefaults to <b>Auto</b>, which will use <b>Sleep</b> for dedicated server builds, and <b>BusyWait</b> for client and server builds (as well as the editor).")]
public ClientServerTickRate.FrameRateMode TargetFrameRateMode
Field Value
Type | Description |
---|---|
ClientServerTickRate.FrameRateMode |
Properties
ClampPartialTicksThreshold
On the client, Netcode attempts to align its own fixed step with the render refresh rate, with the goal of reducing Partial ticks, and increasing stability. This setting denotes the window (in %) to snap and align. Defaults to 5 (5%), which is applied each way: I.e. If you're within 5% of the last full tick, or if you're within 5% of the next full tick, we'll clamp. -1 is 'turn clamping off', 0 is 'use default'. Max value is 50 (i.e. 50% each way, leading to full clamping, as it's applied in both directions).
Declaration
[Tooltip("On the client, Netcode attempts to align its own fixed step with the render refresh rate, with the goal of reducing Partial ticks, and increasing stability.\n\nThis setting denotes the window (in %) to snap and align.\n\nDefaults to 5 (5%), which is applied each way.\nI.e. If you're within 5% of the last full tick, or if you're within 5% of the next full tick, we'll clamp. 50 (50%) to always clamp.")]
public int ClampPartialTicksThreshold { readonly get; set; }
Property Value
Type | Description |
---|---|
int |
Remarks
High values will lead to more aggressive alignment, which may be perceivable (as we'll need to shift time further).
PredictedFixedStepSimulationTimeStep
The fixed time used to run the physics simulation. Is always an integer multiple of the SimulationFixedTimeStep.
The value is equal to 1f / (SimulationTickRate * PredictedFixedStepSimulationTickRatio).
Declaration
public float PredictedFixedStepSimulationTimeStep { get; }
Property Value
Type | Description |
---|---|
float |
SendSnapshotsForCatchUpTicks
If the server has to run multiple simulation ticks in the same frame, the server can either send snapshots for all those ticks (true), or just the last one (false).
Declaration
public bool SendSnapshotsForCatchUpTicks { get; set; }
Property Value
Type | Description |
---|---|
bool |
SimulationFixedTimeStep
1f / SimulationTickRate. Think of this as the netcode version of fixedDeltaTime
.
Declaration
public float SimulationFixedTimeStep { get; }
Property Value
Type | Description |
---|---|
float |
Methods
CalculateNetworkSendRateInterval()
Helper: Returns 1 when NetworkTickRate is equal to (or close enough - via rounding - to) SimulationTickRate. Returns 2 when half, 3 when 1/3rd etc.
Declaration
public int CalculateNetworkSendRateInterval()
Returns
Type | Description |
---|---|
int | The snapshot send interval. |
ResolveDefaults()
Set all the properties that haven't been changed by the user (or that have invalid ranges) to a proper default value. In particular, this guarantees that both NetworkTickRate and SimulationTickRate are never 0.
Declaration
public void ResolveDefaults()