feat: NetworkTickManager (Experimental) - Sync, predict, reconcile using ticks #3996
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(feat) Tick based CSP with prediction and reconciliation
What is the goal:
The goal is to allow a convenient solution to synchronize the Prediction tick and Server Replay ticks to allow for smooth
and CONSISTENT player experience when running server authoritative architecture while minimizing the latency based on network conditions such as packet loss.
Components:
Network Tick Manager (
public class NetworkTickManager : NetworkBehaviour)This is the core component that will handle the clients connection and synchronization by carefully mapping the arrival and delay of sent and received ticks
data.
The actual timing doesn't matter and can be un-equal for sending and receiving.
All we care about is that my current client inputs arrive at the correct time on the server
and that the server send me the information before i replay server characters actions on the client.
To reduce traffic and complexity i am using 0-2047 looping tick numbers. This however doesnt mean there is no absolute tick counter available through the sync
process.
Predicted tick
Server replay tick
Physics Controller (
public class NetworkPhysicsController : MonoBehaviour)Since i have to change when to execute physics simulations and how many this is the result. A simple implementation that allows for networked items to register
and simulate/reconcile correctly.
Execution Order
Network Physics Entity (
public class NetworkPhysicsEntity)This is a static class that stores all the registered items to execute during networked simulation. It should not be used for things like decorations or
particles or anything that does not affect the player and doesnt need to be simulated on clients.
were registered)
Network Tick (
public class NetworkTick)The class NetworkTick is there with static fields to allow for access across the project and consists of several static getters:
How the numbers are calculated:
Client will send his tick to the server and the server will simply return how far the client tick is from the server.
The client will then adjust based on the available data and running minimums.

Same goes for the server but instead of sending to the server we ju
st compare current reply tick with what we receive from the server
Notes:
While testing the most likely tick offset between client predicted and server replay is going to be 2-3.

This is due to Unity fixedUpdate being tied to the framerate and Mirrors optimizations ( batching ).

While 1 tick is possible it is very rare on high tick systems ( 50+ ticks )
Inputs and States structure
Sent and Received data structure:

inputs-and-states-methods
The intention with these custom states is to provide a flexible yet efficient method of transfering data between server and client
To do that i employ the following strategies:
Inputs
Wthere will be only 1 sent packetlived desync
The server and client work similarly ( both for remotely controlled characters ) by actively reconstructing the full inputs by overlaying changes one over the
other.
States ( server to client only )
reconcile from that tick based on the received server state and inputs
viable to reconcile from.
lived desync
The changes are calculated by using
GetChangedStateComparedToandGetChangedInputsComparedTo.The overlaying of changes on previous states/inoputs is done with
OverrideInputsWithandOverrideStateWithThese accept custom additional override and compare functions. ( see bellow )
Inputs And States Additionals
To allow for full flexibility since there is no way for me to know what inputs developers might require i've exposed:
They accept Array of Bytes and by default will be compared bitwise for any changes.
There is a way to optimized this by using:
Network Player Controller Base
This is an abstract class that is meant to control the local character. To use it you need to implement the following functions:
note: Server never reconciles or adjusts
This is it nothing else is required. For network optimization it is recommended to
implement
AdditionalInputsChangeCompare, AdditionalStateChangeCompare, AdditionalInputsOverride and AdditionalStateOverrideReconcile sethods soft and hard
I've implemented 2 ways to reconcile - one is called "hard" and its there to reconcile any significant change in position, rotation or velocity.
hard reconcile
Once player history ( state in the past ) does not match the one received from the server a reconcile flag will be raised and before the next tick a reconcile
will be run.
Reconcile is run by reseting the client state to the tick where the desync was dettected and then running fast forward to the current tick. afterward the next
tick will be executed as usual.
To add additional reconcile triggers please implement
soft reconcile
It is often the case that there are micro changes on the order of 1e-7 or 1e-8 that are not picked up during desync dettection, due to compoinding effect
however they will cause a hard reconcile down the line.
To prevent that the current (predicted) tick will bee adjusts by the small difference in position, rotation or velocity.
note: This has shown to almost negate the need for hard reconcile, however it does not fix anything besides position, rotation or velocity