-
Notifications
You must be signed in to change notification settings - Fork 447
feat: Added support for client anticipation in NetworkVariables and NetworkTransform and support for throttling functionality in NetworkVariables #2820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…g delta computation to save bandwidth.
…tworkVariableUpdateTraits
# Conflicts: # com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs # com.unity.netcode.gameobjects/Runtime/NetworkVariable/CollectionSerializationUtility.cs # com.unity.netcode.gameobjects/Runtime/NetworkVariable/ResizableBitVector.cs
- Ensured that Anticipate*() methods when called on the server will update the authoritative value on AnticipatedNetworkTransform - Disabled the use of interpolation with AnticipatedNetworkTransform because it interacts poorly with anticipation and smoothing, and smoothing accomplishes the same result
…t only sends data once per tick, and sends data at the start of the frame, the "AnticipationTick" value is invalid by the time the data arrives. It now sends a small pulse message on frames where a change is detected so that when the actual data is received later, the anticipation tick value will be accurate.
…narios - Adjusted the way stale data was detected to use an integer value instead of a double to ensure there's no floating point error - Moved stale data detection data into a new AnticipationSystem instead of making it part of NetworkTickSystem - Changed anticipation data exposed to Reanticipate callbacks to use real time rather than ticks to make it easier for users to do time-based calculations
…ly anticipate position, rotation, and scale all at once.
Now all authoritative values are updated for all AnticipatedNetworkVariables AND AnticipatedNetworkTransforms THEN all Reanticipate callbacks are called THEN a global NetworkManager.OnReanticipate() is called once all individual reanticipations have been finished This also moves the timing of applying AnticipatedNetworkTransform's authoritative state to happen immediately upon receiving the message for it, instead of happening during Update(). This helps ensure that whole game state anticipations are possible, for example, if anticipating an AI's behavior relies on updated network variables or on other anticipated objects having completed their anticipations.
…ot properly call the reanticipate callback if stale data handling is set to ignore.
…erver side. (It was already supported for AnticipatedNetworkVariable.) This is important for Hosts to be able to maintain smooth gameplay via interpolation in bad network conditions.
case NetworkUpdateStage.PostScriptLateUpdate: | ||
|
||
AnticipationSystem.Sync(); | ||
AnticipationSystem.SetupForRender(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this concept but would like to know more about it for the DA stuff.
@@ -1997,6 +1997,15 @@ internal void SceneChangedUpdate(Scene scene, bool notify = false) | |||
/// </remarks> | |||
private void Update() | |||
{ | |||
foreach (var behaviour in ChildNetworkBehaviours) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should discuss this as this could mean added performance hit for certain users based on how they use NetworkObject. It was my fault in adding the Update to NetworkObject in the first place, but perhaps we can figure out a way to hook the NetworkVariable update into the NetworkManager.NetworkUpdate method?
com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs
Show resolved
Hide resolved
/// <summary> | ||
/// Gets the tick, including partial tick value passed since it started. | ||
/// </summary> | ||
public double TickWithPartial => Tick + (TickOffset / m_TickInterval); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😻
@@ -19,20 +21,37 @@ private struct MessageData | |||
public static ulong HighTransportId = 0; | |||
public ulong TransportId = 0; | |||
|
|||
public float SimulatedLatencySeconds; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is nice...
I have a bunch of integration tests that need to start using this.
com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really like the the whole thing... just wanted to make sure I understand all of the changes.
Going ahead and approving pending any changes that may come from a 1:1 review (if you have time).
@@ -0,0 +1,70 @@ | |||
namespace Unity.Netcode | |||
{ | |||
internal struct AnticipationCounterSyncPingMessage : INetworkMessage, INetworkSerializeByMemcpy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are there two serialize implementations for this message? INetworkMessage and INetworkSerializeByMemcpy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INetworkMessage
is not a serialization implementation, it is an interface to allow the messagin infrastructure to call Serialize()
on it, which can then serialize in any way. With INetworkSerializeByMemcpy
, it could then call writer.WriteValueSafe(this)
to memcpy the whole thing in. So it's not unreasonable to have both.
But as I'm not doing that, INetworkSerializeByMemcpy
is pretty useless and should be removed. It's a copy/paste error.
} | ||
break; | ||
case NetworkUpdateStage.PreUpdate: | ||
{ | ||
NetworkTimeSystem.UpdateTime(); | ||
AnticipationSystem.Update(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh... you pulled out from the NetworkObject.Update!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me a 2nd time!
👍
Changelog
AnticipatedNetworkVariable<T>
, which adds support for client anticipation of NetworkVariable values, allowing for more responsive gameplayAnticipatedNetworkTransform
, which adds support for client anticipation of NetworkTransformsNetworkVariableBase.ExceedsDirtinessThreshold
to allow network variables to throttle updates by only sending updates when the difference between the current and previous values exceeds a threshold. (This is exposed inNetworkVariable<T>
with the callbackNetworkVariable<T>.CheckExceedsDirtinessThreshold
)NetworkVariableUpdateTraits
, which add additional throttling support:MinSecondsBetweenUpdates
will prevent the NetworkVariable from sending updates more often than the specified time period (even if it exceeds the dirtiness threshold), whileMaxSecondsBetweenUpdates
will force a dirty NetworkVariable to send an update after the specified time period even if it has not yet exceeded the dirtiness threshold.NetworkVariableBase.OnInitialize()
which can be used by NetworkVariable subclasses to add initialization codeNetworkVariableBase.Update()
, which is called once per frame to support behaviors such as interpolation between an anticipated value and an authoritative one.NetworkTime.TickWithPartial
, which represents the current tick as a double that includes the fractional/partial tick value.NetworkTickSystem.AnticipationTick
, which can be helpful with implementation of client anticipation. This value represents the tick the current local client was at at the beginning of the most recent network round trip, which enables it to correlate server update ticks with the client tick that may have triggered them.Testing and Documentation