Skip to content

Commit 3783c64

Browse files
text - fix
This is an attempt to fix an issue where Mac OSX is frequently failing the InterpolationStopAndStartMotionTest. Based on the error, I am thinking (hard to tell since it doesn't replicate locally in-editor nor stand alone) that it could be due to a Mac VM running slower than expected (randomly) which could cause the network tick event to trigger more than once in a single frame.
1 parent db50def commit 3783c64

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

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

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ protected override bool UseCMBService()
3131
private NetworkTransform.InterpolationTypes m_InterpolationType;
3232
private NetworkManager m_AuthorityNetworkManager;
3333

34+
private bool m_IsSecondPass;
35+
private bool m_SecondPassClientsCheckingState;
3436
private int m_NumberOfUpdates;
3537
private Vector3 m_Direction;
3638

@@ -102,8 +104,9 @@ private bool WaitForInstancesToFinishInterpolation()
102104
[UnityTest]
103105
public IEnumerator StopAndStartMotion()
104106
{
107+
m_IsSecondPass = false;
108+
m_SecondPassClientsCheckingState = false;
105109
m_AuthorityNetworkManager = GetAuthorityNetworkManager();
106-
107110
m_AuthorityInstance = SpawnObject(m_TestPrefab, m_AuthorityNetworkManager).GetComponent<TestStartStopTransform>();
108111
// Wait for all clients to spawn the instance
109112
yield return WaitForConditionOrTimeOut(WaitForInstancesToSpawn);
@@ -123,16 +126,11 @@ public IEnumerator StopAndStartMotion()
123126
yield return WaitForConditionOrTimeOut(WaitForInstancesToFinishInterpolation);
124127
AssertOnTimeout($"Not all clients finished interpolating {m_AuthorityInstance.name}!");
125128

126-
// Start recording the state updates on the non-authority instances
127-
foreach (var testTransform in m_NonAuthorityInstances)
128-
{
129-
testTransform.CheckStateUpdates = true;
130-
}
131-
132129
////// Stop to Start motion begins here
133130
m_Direction = GetRandomVector3(-10, 10).normalized;
134131
m_NumberOfUpdates = 0;
135132
m_AuthorityNetworkManager.NetworkTickSystem.Tick += NetworkTickSystem_Tick;
133+
m_IsSecondPass = true;
136134

137135
yield return WaitForConditionOrTimeOut(() => m_NumberOfUpdates >= 10);
138136
AssertOnTimeout($"Timed out waiting for all updates to be applied to the authority instance!");
@@ -155,17 +153,44 @@ public IEnumerator StopAndStartMotion()
155153
/// </summary>
156154
private void NetworkTickSystem_Tick()
157155
{
156+
// In the event a VM is running slower than expected, this counter is used to check
157+
// that we are not invoking the network tick event more than once in a single frame.
158+
// If we are, then exit early since we are just using this to assure that we only
159+
// update the position enough per tick to generate a state update ==and== to prevent
160+
// from incrementing the m_NumberOfUpdates more than once per tick for the frame that
161+
// the tick event was invoked.
162+
if (TestStartStopTransform.TickInvocationCounter >= 1)
163+
{
164+
return;
165+
}
166+
167+
// Start tracking state on a network tick
168+
if (m_IsSecondPass && !m_SecondPassClientsCheckingState)
169+
{
170+
// Start recording the state updates on the non-authority instances
171+
foreach (var testTransform in m_NonAuthorityInstances)
172+
{
173+
testTransform.CheckStateUpdates = true;
174+
}
175+
m_SecondPassClientsCheckingState = true;
176+
}
177+
158178
m_NumberOfUpdates++;
159179
m_AuthorityInstance.transform.position = m_AuthorityInstance.transform.position + m_Direction * 2;
160180
if (m_NumberOfUpdates >= 10)
161181
{
162182
m_AuthorityNetworkManager.NetworkTickSystem.Tick -= NetworkTickSystem_Tick;
163183
}
184+
TestStartStopTransform.TickInvocationCounter++;
164185
}
165186

166-
internal class TestStartStopTransform : NetworkTransform
187+
internal class TestStartStopTransform : NetworkTransform, INetworkUpdateSystem
167188
{
168-
189+
// In the event a VM is running slower than expected, this counter is used to check
190+
// that we are not invoking the network tick event more than once in a single frame.
191+
// If we are, then within the above integration test it will not continue to update
192+
// and increment the counter prematurely.
193+
public static int TickInvocationCounter = 0;
169194
public bool CheckStateUpdates;
170195

171196
private BufferedLinearInterpolatorVector3 m_PosInterpolator;
@@ -184,6 +209,30 @@ protected override void Awake()
184209
m_PosInterpolator = GetPositionInterpolator();
185210
}
186211

212+
protected override void OnNetworkPostSpawn()
213+
{
214+
if (CanCommitToTransform)
215+
{
216+
NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.EarlyUpdate);
217+
}
218+
base.OnNetworkPostSpawn();
219+
}
220+
221+
public void NetworkUpdate(NetworkUpdateStage updateStage)
222+
{
223+
if (updateStage == NetworkUpdateStage.EarlyUpdate)
224+
{
225+
// Each new frame, we reset this counter.
226+
TickInvocationCounter = 0;
227+
}
228+
}
229+
230+
public override void OnNetworkDespawn()
231+
{
232+
NetworkUpdateLoop.UnregisterAllNetworkUpdates(this);
233+
base.OnNetworkDespawn();
234+
}
235+
187236
/// <summary>
188237
/// Checks the time that passed between the first and second state updates.
189238
/// </summary>

0 commit comments

Comments
 (0)