@@ -15,13 +15,15 @@ public abstract class BufferedLinearInterpolator<T> where T : struct
1515 internal float MaxInterpolationBound = 1.0f ;
1616 protected internal struct BufferedItem
1717 {
18+ public int ItemId ;
1819 public T Item ;
1920 public double TimeSent ;
2021
21- public BufferedItem ( T item , double timeSent )
22+ public BufferedItem ( T item , double timeSent , int itemId )
2223 {
2324 Item = item ;
2425 TimeSent = timeSent ;
26+ ItemId = itemId ;
2527 }
2628 }
2729
@@ -34,7 +36,7 @@ public BufferedItem(T item, double timeSent)
3436
3537 protected internal readonly Queue < BufferedItem > m_Buffer = new Queue < BufferedItem > ( k_BufferCountLimit ) ;
3638
37-
39+ private int m_BufferCount ;
3840
3941 // Buffer consumption scenarios
4042 // Perfect case consumption
@@ -88,6 +90,7 @@ internal void ConvertTransformSpace(Transform transform, bool inLocalSpace)
8890 public void Clear ( )
8991 {
9092 m_Buffer . Clear ( ) ;
93+ m_BufferCount = 0 ;
9194 m_CurrentInterpValue = default ;
9295 m_LastMeasurementAddedTime = 0.0 ;
9396 InterpolateState . Reset ( default ) ;
@@ -176,18 +179,26 @@ internal struct CurrentState
176179 {
177180 public BufferedItem ? Target ;
178181
182+ public double ServerTime ;
179183 public double RelativeTime ;
184+ public double DeltaTime ;
180185
181186 public T CurrentValue ;
187+ public T PreviousValue ;
182188
183189 public float LerpT ;
184190
191+ public float LerpV ;
192+
185193 public void Reset ( T currentValue )
186194 {
187195 CurrentValue = currentValue ;
196+ PreviousValue = currentValue ;
188197 // When reset, we consider ourselves to have already arrived at the target (even if no target is set)
189198 LerpT = 1.0f ;
199+ LerpV = 1.0f ;
190200 RelativeTime = 0.0 ;
201+ DeltaTime = 0.0 ;
191202 }
192203 }
193204
@@ -235,15 +246,192 @@ private void TryConsumeFromBuffer(double renderTime, double serverTime)
235246 }
236247 }
237248
249+
250+ #if UNITY_EDITOR
251+ internal bool EnableLogging = false ;
252+ internal ulong NetworkObjectId ;
253+ internal ushort NetworkBehaviourId ;
254+
255+ private double m_LastDebugUpdate = 0.0 ;
256+
257+ private double m_AvgTimeDelta = 0.0 ;
258+
259+ private float m_LowestLerpT = float . MaxValue ;
260+ private float m_LerpTAverage = 0.0f ;
261+ private int m_MaxBufferedItems = 0 ;
262+ private float m_AverageBufferCount = 0.0f ;
263+
264+ private void LogInfo ( double serverTime )
265+ {
266+ if ( ! EnableLogging )
267+ {
268+ return ;
269+ }
270+ if ( m_LowestLerpT > InterpolateState . LerpT )
271+ {
272+ m_LowestLerpT = InterpolateState . LerpT ;
273+ }
274+
275+ if ( m_LerpTAverage == 0.0f )
276+ {
277+ m_LerpTAverage = InterpolateState . LerpT ;
278+ }
279+ else
280+ {
281+ m_LerpTAverage = ( m_LerpTAverage + InterpolateState . LerpT ) * 0.5f ;
282+ }
283+
284+ if ( m_MaxBufferedItems < m_Buffer . Count )
285+ {
286+ m_MaxBufferedItems = m_Buffer . Count ;
287+ }
288+
289+ if ( m_AverageBufferCount == 0.0f )
290+ {
291+ m_AverageBufferCount = ( m_AverageBufferCount + m_Buffer . Count ) * 0.5f ;
292+ }
293+
294+ if ( m_AvgTimeDelta == 0.0 )
295+ {
296+ m_AvgTimeDelta = InterpolateState . DeltaTime ;
297+ }
298+ else
299+ {
300+ m_AvgTimeDelta += InterpolateState . DeltaTime ;
301+ m_AvgTimeDelta *= 0.5 ;
302+ }
303+
304+ if ( m_LastDebugUpdate < serverTime )
305+ {
306+ Debug . Log ( $ "[{ m_Name } ][{ NetworkObjectId } -{ NetworkBehaviourId } ][{ InterpolateState . Target . Value . ItemId } ] Min LerpT: { m_LowestLerpT } | Avg LerpT: { m_LerpTAverage } | Max Count: { m_MaxBufferedItems } | Avg Count: { m_AverageBufferCount } | Avg TD: { m_AvgTimeDelta } ") ;
307+ m_LastDebugUpdate = serverTime + 1.0 ;
308+ m_AverageBufferCount = 0.0f ;
309+ m_MaxBufferedItems = 0 ;
310+ m_LerpTAverage = 0.0f ;
311+ m_LowestLerpT = float . MaxValue ;
312+ }
313+ }
314+ #endif
315+
316+ private void TryConsumeFromBuffer ( NetworkTime networkTime , NetworkTimeSystem networkTimeSystem )
317+ {
318+ // If we don't have our initial buffered item/starting point or our end point or the end point's time sent is less than the
319+ // render time
320+ var renderTime = networkTime . TimeTicksAgo ( 2 ) . Time ;
321+ if ( ! InterpolateState . Target . HasValue || ( InterpolateState . Target . Value . TimeSent <= renderTime && InterpolateState . LerpT >= 1.0f ) )
322+ {
323+ BufferedItem ? previousItem = null ;
324+ while ( m_Buffer . TryPeek ( out BufferedItem potentialItem ) )
325+ {
326+ // If we are still on the same buffered item (FIFO Queue), then exit early as there is nothing
327+ // to consume.
328+ if ( previousItem . HasValue && previousItem . Value . TimeSent == potentialItem . TimeSent )
329+ {
330+ break ;
331+ }
332+
333+ // At a minimum, the next item should be equal to or less than the server time
334+ if ( potentialItem . TimeSent <= networkTimeSystem . ServerTime )
335+ {
336+ if ( ! InterpolateState . Target . HasValue || InterpolateState . Target . Value . TimeSent < potentialItem . TimeSent )
337+ {
338+ if ( m_Buffer . TryDequeue ( out BufferedItem target ) )
339+ {
340+ if ( ! InterpolateState . Target . HasValue )
341+ {
342+ InterpolateState . Target = target ;
343+ InterpolateState . DeltaTime = networkTime . FixedDeltaTime ;
344+ }
345+ else
346+ {
347+ #if UNITY_EDITOR
348+ LogInfo ( networkTimeSystem . ServerTime ) ;
349+ #endif
350+ InterpolateState . DeltaTime = networkTime . FixedDeltaTime ;
351+ InterpolateState . Target = target ;
352+ }
353+ //InterpolateState.RelativeTime = networkTime.FixedDeltaTime/2.75f;
354+ //InterpolateState.RelativeTime = networkTime.FixedDeltaTime / 3f;
355+ InterpolateState . RelativeTime = 0.0 ;
356+ InterpolateState . PreviousValue = InterpolateState . CurrentValue ;
357+ InterpolateState . LerpT = 0.0f ;
358+ InterpolateState . LerpV = 0.0f ;
359+ InterpolateState . ServerTime = networkTimeSystem . ServerTime ;
360+ break ;
361+ }
362+ }
363+ else
364+ {
365+ break ;
366+ }
367+ }
368+ if ( ! InterpolateState . Target . HasValue )
369+ {
370+ break ;
371+ }
372+ previousItem = potentialItem ;
373+ }
374+ }
375+ }
376+
377+
238378 /// <summary>
239- /// Convenience version of 'Update' mainly for testing
240- /// the reason we don't want to always call this version is so that on the calling side we can compute
241- /// the renderTime once for the many things being interpolated (and the many interpolators per object)
379+ /// ** Recommended Usage **
380+ /// A more precise update for the buffered linear interpolator.
242381 /// </summary>
243382 /// <param name="deltaTime">time since call</param>
244383 /// <param name="serverTime">current server time</param>
245384 /// <returns>The newly interpolated value of type 'T'</returns>
246- public T Update ( float deltaTime , NetworkTime serverTime )
385+ public T Update ( float deltaTime , NetworkTime serverTime , NetworkTimeSystem networkTimeSystem )
386+ {
387+ TryConsumeFromBuffer ( serverTime , networkTimeSystem ) ;
388+
389+
390+ // Only interpolate when there is a start and end point and we have not already reached the end value
391+ if ( InterpolateState . Target . HasValue )
392+ {
393+ if ( InterpolateState . LerpT < 1.0f )
394+ {
395+ var serverTimeDelta = Math . Max ( 0.000000000001 , ( networkTimeSystem . ServerTime - InterpolateState . ServerTime ) + deltaTime ) ;
396+
397+ InterpolateState . RelativeTime = Math . Min ( InterpolateState . RelativeTime + serverTimeDelta , InterpolateState . DeltaTime ) ;
398+
399+ #if UNITY_EDITOR
400+ //if (EnableLogging)
401+ //{
402+ // Debug.Log($"[{m_Name}][{NetworkObjectId}-{NetworkBehaviourId}][{InterpolateState.Target.Value.ItemId}] Server Time: {networkTimeSystem.ServerTime} | Time RDelta: {InterpolateState.RelativeTime} | Delta: {InterpolateState.DeltaTime}");
403+ //}
404+ #endif
405+ //var t = 1.0f - Mathf.Clamp((float)((m_EndTimeConsumed - renderTime) * rangeFactor), 0.0f, 1.0f);
406+ //var alt_t = 1.0f - Mathf.Clamp((float)((renderTime - m_StartTimeConsumed) * rangeFactor), 0.0f, 1.0f);
407+ InterpolateState . LerpT = ( float ) ( InterpolateState . RelativeTime / InterpolateState . DeltaTime ) ;
408+ InterpolateState . CurrentValue = Interpolate ( InterpolateState . PreviousValue , InterpolateState . Target . Value . Item , InterpolateState . LerpT ) ;
409+ m_CurrentInterpValue = InterpolateState . CurrentValue ;
410+ //m_CurrentInterpValue = Interpolate(InterpolateState.TargetStartValue, InterpolateState.TargetEndValue, (deltaTime / MaximumInterpolationTime));
411+ //if (InterpolateState.LerpT < 1.0f)
412+ //{
413+ // m_CurrentInterpValue = Interpolate(m_CurrentInterpValue, InterpolateState.CurrentValue, 0.5f);
414+ //}
415+ //else
416+ //{
417+ // m_CurrentInterpValue = InterpolateState.CurrentValue;
418+ //}
419+ //if (InterpolateState.LerpT >= 1.0f)
420+ //{
421+ // InterpolateState.TargetValue = InterpolateState.CurrentValue;
422+ //}
423+ //InterpolateState.LerpV = Math.Min(InterpolateState.LerpV + (deltaTime / MaximumInterpolationTime), 1.0f);
424+ }
425+ }
426+
427+ m_NbItemsReceivedThisFrame = 0 ;
428+ return m_CurrentInterpValue ;
429+ }
430+
431+ /// <summary>
432+ /// Used for internal testing
433+ /// </summary>
434+ internal T UpdateInternal ( float deltaTime , NetworkTime serverTime )
247435 {
248436 return Update ( deltaTime , serverTime . TimeTicksAgo ( 1 ) . Time , serverTime . Time ) ;
249437 }
@@ -299,7 +487,8 @@ public void AddMeasurement(T newMeasurement, double sentTime)
299487 {
300488 if ( m_LastBufferedItemReceived . TimeSent < sentTime )
301489 {
302- m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime ) ;
490+ m_BufferCount ++ ;
491+ m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount ) ;
303492 ResetTo ( newMeasurement , sentTime ) ;
304493 // Next line keeps renderTime above m_StartTimeConsumed. Fixes pause/unpause issues
305494 m_Buffer . Enqueue ( m_LastBufferedItemReceived ) ;
@@ -310,7 +499,8 @@ public void AddMeasurement(T newMeasurement, double sentTime)
310499
311500 if ( sentTime > m_LastMeasurementAddedTime )
312501 {
313- m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime ) ;
502+ m_BufferCount ++ ;
503+ m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount ) ;
314504 m_Buffer . Enqueue ( m_LastBufferedItemReceived ) ;
315505 m_LastMeasurementAddedTime = sentTime ;
316506 }
0 commit comments