Skip to content

Commit cfe40d8

Browse files
Merge branch 'develop-2.0.0' into pr-template-improvement
2 parents 40b1fb1 + 15263c7 commit cfe40d8

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
2222

2323
### Fixed
2424

25+
- Fixed issue where a client, under above average latency and packet loss conditions, could receive multiple NetworkTransform state updates in one frame and when processing the state updates only the last state update would be applied to the transform if interpolation was disabled. (#3614)
26+
2527

2628
### Security
2729

com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3003,7 +3003,7 @@ private void ApplyTeleportingState(NetworkTransformState newState)
30033003
/// <remarks>
30043004
/// Only non-authoritative instances should invoke this
30053005
/// </remarks>
3006-
private void ApplyUpdatedState(NetworkTransformState newState)
3006+
internal void ApplyUpdatedState(NetworkTransformState newState)
30073007
{
30083008
// Set the transforms's synchronization modes
30093009
InLocalSpace = newState.InLocalSpace;
@@ -3052,6 +3052,7 @@ private void ApplyUpdatedState(NetworkTransformState newState)
30523052

30533053
if (!Interpolate)
30543054
{
3055+
ApplyAuthoritativeState();
30553056
return;
30563057
}
30573058

com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformGeneral.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,72 @@ protected override void OnOneTimeTearDown()
3737
base.OnOneTimeTearDown();
3838
}
3939

40+
/// <summary>
41+
/// This validates an issue where if multiple state updates are received in a single frame
42+
/// and interpolation is disabled, only the last state udpate processed gets applied.
43+
/// </summary>
44+
[Test]
45+
public void TestMultipleStateSynchronization([Values] bool isLocal, [Values] bool timeTravelBetweenStateUpdates)
46+
{
47+
// Assure no new state updates are pushed.
48+
TimeTravel(0.5f, 60);
49+
50+
// Disable interpolation and set world or local space
51+
m_NonAuthoritativeTransform.Interpolate = false;
52+
m_NonAuthoritativeTransform.InLocalSpace = isLocal;
53+
54+
// Get the non-authority's state
55+
var localState = m_NonAuthoritativeTransform.LocalAuthoritativeNetworkState;
56+
57+
// Assure this is not set to avoid a false positive result with teleporting
58+
localState.IsTeleportingNextFrame = false;
59+
60+
// Simulate a state update
61+
localState.UseInterpolation = false;
62+
localState.CurrentPosition = new Vector3(5.0f, 0.0f, 0.0f);
63+
localState.HasPositionX = true;
64+
localState.PositionX = 5.0f;
65+
localState.NetworkTick++;
66+
67+
var lastStateTick = localState.NetworkTick;
68+
// Apply the simualted state update to the non-authority instance
69+
m_NonAuthoritativeTransform.ApplyUpdatedState(localState);
70+
// Simulate both having time between state updates and having state updates delivered back to back on the same frame
71+
if (timeTravelBetweenStateUpdates)
72+
{
73+
TimeTravelAdvanceTick();
74+
}
75+
76+
// Validate the state update was applied
77+
var xValue = isLocal ? m_NonAuthoritativeTransform.transform.localPosition.x : m_NonAuthoritativeTransform.transform.position.x;
78+
Assert.IsTrue(xValue == 5.0f, $"[Test1][IsLocal: {isLocal}] X axis ({xValue}) does not equal 5.0f!");
79+
80+
81+
// Get the non-authority state
82+
localState = m_NonAuthoritativeTransform.LocalAuthoritativeNetworkState;
83+
84+
//Assure we have not received any state updates from the authority that could skew the test
85+
Assert.IsTrue(localState.NetworkTick == lastStateTick, $"Previous Non-authority state tick was {lastStateTick} but is now {localState.NetworkTick}. Authority pushed a state update.");
86+
87+
// Simualate a 2nd state update on a different position axis
88+
localState.HasPositionX = false;
89+
localState.HasPositionZ = true;
90+
localState.PositionZ = -5.0f;
91+
localState.NetworkTick++;
92+
m_NonAuthoritativeTransform.ApplyUpdatedState(localState);
93+
// Simulate both having time between state updates and having state updates delivered back to back on the same frame
94+
if (timeTravelBetweenStateUpdates)
95+
{
96+
TimeTravelAdvanceTick();
97+
}
98+
var zValue = isLocal ? m_NonAuthoritativeTransform.transform.localPosition.z : m_NonAuthoritativeTransform.transform.position.z;
99+
xValue = isLocal ? m_NonAuthoritativeTransform.transform.localPosition.x : m_NonAuthoritativeTransform.transform.position.x;
100+
101+
// Verify the previous state update's position and current state update's position
102+
Assert.IsTrue(xValue == 5.0f, $"[Test2][IsLocal: {isLocal}] X axis ({xValue}) does not equal 5.0f!");
103+
Assert.IsTrue(zValue == -5.0f, $"[Test2][IsLocal: {isLocal}] Z axis ({zValue}) does not equal -5.0f!");
104+
}
105+
40106
/// <summary>
41107
/// Test to verify nonAuthority cannot change the transform directly
42108
/// </summary>

0 commit comments

Comments
 (0)