diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md
index 13f6126579..d3417214a5 100644
--- a/com.unity.netcode.gameobjects/CHANGELOG.md
+++ b/com.unity.netcode.gameobjects/CHANGELOG.md
@@ -15,6 +15,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
### Fixed
+- Fixed issue where `AnticipatedNetworkVariable` previous value returned by `AnticipatedNetworkVariable.OnAuthoritativeValueChanged` is updated correctly on the non-authoritative side. (#3306)
- Fixed `OnClientConnectedCallback` passing incorrect `clientId` when scene management is disabled. (#3312)
- Fixed issue where the `NetworkObject.Ownership` custom editor did not take the default "Everything" flag into consideration. (#3305)
- Fixed DestroyObject flow on non-authority game clients. (#3291)
diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs
index d9d4e87393..94625722e3 100644
--- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs
+++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs
@@ -387,6 +387,9 @@ public override void ReadField(FastBufferReader reader)
public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
{
m_AuthoritativeValue.ReadDelta(reader, keepDirtyDelta);
+ // Assure that the post delta read is invoked in order to update
+ // previous value.
+ m_AuthoritativeValue.PostDeltaRead();
}
}
}
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs
index c436275fea..66d2d8d90f 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableAnticipationTests.cs
@@ -416,5 +416,39 @@ public void WhenStaleDataArrivesToReanticipatedVariable_ItIsAppliedAndReanticipa
Assert.AreEqual(25, otherClientComponent.ReanticipateOnAnticipationFailVariable.Value);
Assert.AreEqual(20, otherClientComponent.ReanticipateOnAnticipationFailVariable.AuthoritativeValue);
}
+
+
+ private int m_PreviousSnapValue;
+ ///
+ /// Validates the previous value is being properly updated on the non-authoritative side.
+ ///
+ [Test]
+ public void PreviousValueIsMaintainedProperly()
+ {
+ var testComponent = GetTestComponent();
+
+ testComponent.SnapOnAnticipationFailVariable.OnAuthoritativeValueChanged += OnAuthoritativeValueChanged;
+ testComponent.SnapOnAnticipationFailVariable.Anticipate(10);
+ testComponent.SetSnapValueRpc(10);
+ WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList());
+ // Verify the previous value is 0
+ Assert.AreEqual(0, m_PreviousSnapValue);
+ testComponent.SetSnapValueRpc(20);
+
+ WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList());
+ // Verify the previous value is 10
+ Assert.AreEqual(10, m_PreviousSnapValue);
+
+ testComponent.SetSnapValueRpc(30);
+ WaitForMessageReceivedWithTimeTravel(m_ClientNetworkManagers.ToList());
+ // Verify the previous value is 20
+ Assert.AreEqual(20, m_PreviousSnapValue);
+ }
+
+ private void OnAuthoritativeValueChanged(AnticipatedNetworkVariable anticipatedValue, in int previous, in int current)
+ {
+ m_PreviousSnapValue = previous;
+ }
+
}
}