Skip to content

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

Merged
merged 37 commits into from
Mar 27, 2024

Conversation

ShadauxCat
Copy link
Collaborator

Changelog

  • Added: Added AnticipatedNetworkVariable<T>, which adds support for client anticipation of NetworkVariable values, allowing for more responsive gameplay
  • Added: Added AnticipatedNetworkTransform, which adds support for client anticipation of NetworkTransforms
  • Added: Added NetworkVariableBase.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 in NetworkVariable<T> with the callback NetworkVariable<T>.CheckExceedsDirtinessThreshold)
  • Added: Added 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), while MaxSecondsBetweenUpdates will force a dirty NetworkVariable to send an update after the specified time period even if it has not yet exceeded the dirtiness threshold.
  • Added: Added virtual method NetworkVariableBase.OnInitialize() which can be used by NetworkVariable subclasses to add initialization code
  • Added: Added virtual method NetworkVariableBase.Update(), which is called once per frame to support behaviors such as interpolation between an anticipated value and an authoritative one.
  • Added: Added NetworkTime.TickWithPartial, which represents the current tick as a double that includes the fractional/partial tick value.
  • Added: Added 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

  • Includes integration tests.
  • Includes documentation for previously-undocumented public API entry points.
  • Includes edits to existing public API documentation.

# 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
@ShadauxCat ShadauxCat requested a review from a team as a code owner February 2, 2024 20:49
ShadauxCat and others added 22 commits February 2, 2024 14:51
- 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();
Copy link
Collaborator

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)
Copy link
Collaborator

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?

/// <summary>
/// Gets the tick, including partial tick value passed since it started.
/// </summary>
public double TickWithPartial => Tick + (TickOffset / m_TickInterval);
Copy link
Collaborator

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;
Copy link
Collaborator

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.

Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity left a 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

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

Copy link
Collaborator Author

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();
Copy link
Collaborator

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!
:godmode:

Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity left a 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!
👍

@ShadauxCat ShadauxCat enabled auto-merge (squash) March 26, 2024 15:34
@ShadauxCat ShadauxCat merged commit b9fe0d2 into develop Mar 27, 2024
24 checks passed
@ShadauxCat ShadauxCat deleted the feat/NetworkVariable_Traits_And_Anticipation branch March 27, 2024 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants