From bd2898c251e7c77d1ebf1a3c1d17a586bee6cf32 Mon Sep 17 00:00:00 2001 From: "CTHULHU\\Ben" Date: Sat, 24 Aug 2024 19:42:11 -0400 Subject: [PATCH 1/5] get a more accurate local time by using half the RTT. --- .../Runtime/Timing/NetworkTimeSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs b/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs index 4dbd85a046..d6354a450a 100644 --- a/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs +++ b/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs @@ -248,7 +248,7 @@ public void Sync(double serverTimeSec, double rttSec) var timeDif = serverTimeSec - m_TimeSec; m_DesiredServerTimeOffset = timeDif - ServerBufferSec; - m_DesiredLocalTimeOffset = timeDif + rttSec + LocalBufferSec; + m_DesiredLocalTimeOffset = timeDif + (rttSec * 0.5d) + LocalBufferSec; } } } From a1c086e6fe521d5fea5b534c63f5f7446b258608 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 15 Jan 2025 18:45:25 -0600 Subject: [PATCH 2/5] test Adjusting ClientNetworkTimeSystemTests to account for half RTT adjustment applied in this PR. --- .../Timing/ClientNetworkTimeSystemTests.cs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs index 275e891efa..21db991b88 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs @@ -18,15 +18,16 @@ internal class ClientNetworkTimeSystemTests public void StableRttTest() { double receivedServerTime = 2; - - var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, 0.1d); + var baseRtt = 0.1f; + var halfRtt = 0.05f; + var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, baseRtt); timeSystem.Reset(receivedServerTime, 0.15); var tickSystem = new NetworkTickSystem(60, timeSystem.LocalTime, timeSystem.ServerTime); Assert.True(timeSystem.LocalTime > 2); - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, 0.095f, 0.105f, 42); // 10ms jitter + var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, baseRtt, 42); + var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, baseRtt - 0.05f, baseRtt + 0.05f, 42); // 10ms jitter // run for a while so that we reach regular RTT offset TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) @@ -37,10 +38,11 @@ public void StableRttTest() }); // check how we close we are to target time. - var expectedRtt = 0.1d; - var offsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; + var offsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - halfRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; Debug.Log($"offset to target time after running for a while: {offsetToTarget}"); - Assert.IsTrue(Math.Abs(offsetToTarget) < k_AcceptableRttOffset); + + // server speedup/slowdowns should not be affected by RTT + Assert.True(Math.Abs(offsetToTarget) < k_AcceptableRttOffset, $"Expected offset time to be less than {k_AcceptableRttOffset}ms but it was {offsetToTarget}!"); // run again, test that we never need to speed up or slow down under stable RTT TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) @@ -51,9 +53,10 @@ public void StableRttTest() }); // check again to ensure we are still close to the target - var newOffsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; + var newOffsetToTarget = (timeSystem.LocalTime - timeSystem.ServerTime) - halfRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec; Debug.Log($"offset to target time after running longer: {newOffsetToTarget}"); - Assert.IsTrue(Math.Abs(newOffsetToTarget) < k_AcceptableRttOffset); + // server speedup/slowdowns should not be affected by RTT + Assert.True(Math.Abs(offsetToTarget) < k_AcceptableRttOffset, $"Expected offset time to be less than {k_AcceptableRttOffset}ms but it was {offsetToTarget}!"); // difference between first and second offset should be minimal var dif = offsetToTarget - newOffsetToTarget; @@ -67,13 +70,14 @@ public void StableRttTest() public void RttCatchupSlowdownTest() { double receivedServerTime = 2; - - var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, 0.1d); + var baseRtt = 0.1f; + var halfRtt = 0.05f; + var timeSystem = new NetworkTimeSystem(0.05d, 0.05d, baseRtt); timeSystem.Reset(receivedServerTime, 0.15); var tickSystem = new NetworkTickSystem(60, timeSystem.LocalTime, timeSystem.ServerTime); - var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, 0.1f, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, 0.095f, 0.105f, 42); // 10ms jitter + var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, baseRtt, 42); + var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, baseRtt - 0.05f, baseRtt + 0.05f, 42); // 10ms jitter // run for a while so that we reach regular RTT offset TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step) @@ -102,11 +106,14 @@ public void RttCatchupSlowdownTest() // speed up of 0.1f expected Debug.Log($"Total local speed up time catch up: {totalLocalSpeedUpTime}"); - Assert.True(Math.Abs(totalLocalSpeedUpTime - 0.1) < k_AcceptableRttOffset); - Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset); // server speedup/slowdowns should not be affected by RTT + var expectedSpeedUpTime = Math.Abs(totalLocalSpeedUpTime - halfRtt); + var expectedServerSpeedUpTime = Math.Abs(totalServerSpeedUpTime); + Assert.True(expectedSpeedUpTime < k_AcceptableRttOffset, $"Expected local speed up time to be less than {k_AcceptableRttOffset}ms but it was {expectedSpeedUpTime}!"); + // server speedup/slowdowns should not be affected by RTT + Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset, $"Expected server speed up time to be less than {k_AcceptableRttOffset}ms but it was {expectedServerSpeedUpTime}!"); - // run again with RTT ~100ms and see whether we slow down by -0.1f + // run again with RTT ~100ms and see whether we slow down by -halfRtt unscaledLocalTime = timeSystem.LocalTime; unscaledServerTime = timeSystem.ServerTime; @@ -121,13 +128,13 @@ public void RttCatchupSlowdownTest() totalLocalSpeedUpTime = timeSystem.LocalTime - unscaledLocalTime; totalServerSpeedUpTime = timeSystem.ServerTime - unscaledServerTime; - - // slow down of 0.1f expected + // slow down of half halfRtt expected Debug.Log($"Total local speed up time slow down: {totalLocalSpeedUpTime}"); - Assert.True(Math.Abs(totalLocalSpeedUpTime + 0.1) < k_AcceptableRttOffset); - Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset); // server speedup/slowdowns should not be affected by RTT - - + expectedSpeedUpTime = Math.Abs(totalLocalSpeedUpTime + halfRtt); + expectedServerSpeedUpTime = Math.Abs(totalServerSpeedUpTime); + Assert.True(expectedSpeedUpTime < k_AcceptableRttOffset, $"Expected local speed up time to be less than {k_AcceptableRttOffset}ms but it was {expectedSpeedUpTime}!"); + // server speedup/slowdowns should not be affected by RTT + Assert.True(Math.Abs(totalServerSpeedUpTime) < k_AcceptableRttOffset, $"Expected server speed up time to be less than {k_AcceptableRttOffset}ms but it was {expectedServerSpeedUpTime}!"); } /// @@ -172,8 +179,8 @@ public void ResetTest() receivedServerTime += steps[step]; timeSystem.Sync(receivedServerTime, rttSteps2[step]); - // after hard reset time should stay close to rtt - var expectedRtt = 0.5d; + // after hard reset time should stay close to half rtt + var expectedRtt = 0.25d; Assert.IsTrue(Math.Abs((timeSystem.LocalTime - timeSystem.ServerTime) - expectedRtt - timeSystem.ServerBufferSec - timeSystem.LocalBufferSec) < k_AcceptableRttOffset); }); From 6e6c39314ef781f8d01266cef47126825b17e9fd Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 15 Jan 2025 18:48:53 -0600 Subject: [PATCH 3/5] style Adding a comment about the change --- .../Runtime/Timing/NetworkTimeSystem.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs b/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs index d6354a450a..41327dbcd2 100644 --- a/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs +++ b/com.unity.netcode.gameobjects/Runtime/Timing/NetworkTimeSystem.cs @@ -248,6 +248,8 @@ public void Sync(double serverTimeSec, double rttSec) var timeDif = serverTimeSec - m_TimeSec; m_DesiredServerTimeOffset = timeDif - ServerBufferSec; + // We adjust our desired local time offset to be half RTT since the delivery of + // the TimeSyncMessage should only take half of the RTT time (legacy was using 1 full RTT) m_DesiredLocalTimeOffset = timeDif + (rttSec * 0.5d) + LocalBufferSec; } } From 7c1eaa7346a20f558e7a181cd26474ae0acc12a6 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Sun, 19 Jan 2025 10:53:10 -0600 Subject: [PATCH 4/5] update Adding changelog entry --- com.unity.netcode.gameobjects/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index c20a80df87..8f2dee46b1 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -12,6 +12,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed +- Changed the `NetworkTimeSystem.Sync` method to use half RTT to calculate the desired local time offset as opposed to the full RTT. (#3212) - Fixed issue where a spawned `NetworkObject` that was registered with a prefab handler and owned by a client would invoke destroy more than once on the host-server side if the client disconnected while the `NetworkObject` was still spawned. (#3200) ### Changed From 525613aa72adc58591e071bbd9fa8ec85295087c Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Sun, 19 Jan 2025 10:55:25 -0600 Subject: [PATCH 5/5] style removing white space after comment --- .../Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs index 21db991b88..fc7cb01d69 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Timing/ClientNetworkTimeSystemTests.cs @@ -27,7 +27,7 @@ public void StableRttTest() Assert.True(timeSystem.LocalTime > 2); var steps = TimingTestHelper.GetRandomTimeSteps(100f, 0.01f, baseRtt, 42); - var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, baseRtt - 0.05f, baseRtt + 0.05f, 42); // 10ms jitter + var rttSteps = TimingTestHelper.GetRandomTimeSteps(1000f, baseRtt - 0.05f, baseRtt + 0.05f, 42); // 10ms jitter // run for a while so that we reach regular RTT offset TimingTestHelper.ApplySteps(timeSystem, tickSystem, steps, delegate (int step)