@@ -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