@@ -87,6 +87,10 @@ private float GetPrecision()
8787 /// </summary>
8888 protected internal struct BufferedItem
8989 {
90+ /// <summary>
91+ /// The transform parent for this specific value measurement.
92+ /// </summary>
93+ internal Transform MeasurementParent ;
9094 /// <summary>
9195 /// The item identifier
9296 /// </summary>
@@ -111,6 +115,7 @@ public BufferedItem(T item, double timeSent, int itemId)
111115 Item = item ;
112116 TimeSent = timeSent ;
113117 ItemId = itemId ;
118+ MeasurementParent = default ;
114119 }
115120
116121 /// <summary>
@@ -124,6 +129,7 @@ public BufferedItem(T item, double timeSent)
124129 TimeSent = timeSent ;
125130 // Generate a unique item id based on the time to the 2nd decimal place
126131 ItemId = ( int ) ( timeSent * 100 ) ;
132+ MeasurementParent = default ;
127133 }
128134 }
129135
@@ -135,6 +141,7 @@ public BufferedItem(T item, double timeSent)
135141 /// </remarks>
136142 internal struct CurrentState
137143 {
144+ public Transform TargetParent ;
138145 public BufferedItem ? Target ;
139146 public double StartTime ;
140147 public double EndTime ;
@@ -225,7 +232,7 @@ public void Reset(T currentValue)
225232 /// </summary>
226233 internal float MaxInterpolationBound = 3.0f ;
227234 internal bool EndOfBuffer => m_BufferQueue . Count == 0 ;
228- internal bool StoreAsWorldSpace ;
235+ internal bool AutoConvertTransformSpace ;
229236 internal bool InLocalSpace ;
230237 internal Transform Parent ;
231238
@@ -271,22 +278,41 @@ internal void ResetTo(Transform parent, T targetValue, double serverTime)
271278 }
272279
273280 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
274- private bool ConvertTransformSpace ( Transform parent )
281+ private void ConvertInterpolateStateValues ( Transform parent , bool inLocalSpace )
275282 {
276- return StoreAsWorldSpace && parent != null && InLocalSpace ;
283+ InterpolateState . CurrentValue = OnConvertTransformSpace ( parent , InterpolateState . CurrentValue , inLocalSpace ) ;
284+ InterpolateState . NextValue = OnConvertTransformSpace ( parent , InterpolateState . NextValue , inLocalSpace ) ;
285+ InterpolateState . PreviousValue = OnConvertTransformSpace ( parent , InterpolateState . PreviousValue , inLocalSpace ) ;
277286 }
278287
288+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
289+ private void ConvertTransformSpace ( )
290+ {
291+ if ( ! AutoConvertTransformSpace )
292+ {
293+ return ;
294+ }
295+ if ( InterpolateState . TargetParent != Parent )
296+ {
297+ if ( InterpolateState . TargetParent != null )
298+ {
299+ // Convert to world space.
300+ ConvertInterpolateStateValues ( InterpolateState . TargetParent , false ) ;
301+ }
302+
303+ if ( Parent != null )
304+ {
305+ // Convert to local space.
306+ ConvertInterpolateStateValues ( Parent , true ) ;
307+ }
308+ }
309+ }
279310
280311 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
281312 private void InternalReset ( Transform parent , T targetValue , double serverTime , bool addMeasurement = true )
282313 {
283314 m_RateOfChange = default ;
284315 var currentValue = targetValue ;
285- if ( ConvertTransformSpace ( parent ) )
286- {
287- // Keep everything in world space
288- currentValue = OnConvertTransformSpace ( parent , targetValue , false ) ;
289- }
290316
291317 // Set our initial value (what we will interpolate from relative to the next state update received)
292318 InterpolateState . Reset ( currentValue ) ;
@@ -340,6 +366,8 @@ private void TryConsumeFromBuffer(double renderTime, double minDeltaTime, double
340366 {
341367 if ( m_BufferQueue . TryDequeue ( out BufferedItem target ) )
342368 {
369+ ConvertTransformSpace ( ) ;
370+
343371 if ( ! InterpolateState . Target . HasValue )
344372 {
345373 InterpolateState . Target = target ;
@@ -365,6 +393,7 @@ private void TryConsumeFromBuffer(double renderTime, double minDeltaTime, double
365393 InterpolateState . SetTimeToTarget ( Math . Max ( target . TimeSent - startTime , minDeltaTime ) ) ;
366394 InterpolateState . Target = target ;
367395 }
396+ InterpolateState . TargetParent = target . MeasurementParent ;
368397 }
369398 }
370399 else
@@ -487,6 +516,7 @@ private void TryConsumeFromBuffer(double renderTime, double serverTime)
487516 {
488517 if ( m_BufferQueue . TryDequeue ( out BufferedItem target ) )
489518 {
519+ ConvertTransformSpace ( ) ;
490520 if ( ! InterpolateState . Target . HasValue )
491521 {
492522 InterpolateState . Target = target ;
@@ -509,6 +539,7 @@ private void TryConsumeFromBuffer(double renderTime, double serverTime)
509539 InterpolateState . TimeToTargetValue = InterpolateState . EndTime - InterpolateState . StartTime ;
510540 InterpolateState . Target = target ;
511541 }
542+ InterpolateState . TargetParent = target . MeasurementParent ;
512543 }
513544 }
514545
@@ -535,7 +566,7 @@ public T Update(float deltaTime, double renderTime, double serverTime)
535566 {
536567 TryConsumeFromBuffer ( renderTime , serverTime ) ;
537568 // Only interpolate when there is a start and end point and we have not already reached the end value
538- if ( InterpolateState . Target . HasValue && ! InterpolateState . TargetReached )
569+ if ( ! InterpolateState . TargetReached && InterpolateState . Target . HasValue )
539570 {
540571 // The original BufferedLinearInterpolator lerping script to assure the Smooth Dampening updates do not impact
541572 // this specific behavior.
@@ -561,7 +592,7 @@ public T Update(float deltaTime, double renderTime, double serverTime)
561592 InterpolateState . TargetReached = IsApproximately ( InterpolateState . CurrentValue , InterpolateState . Target . Value . Item , GetPrecision ( ) ) ;
562593 }
563594 else // If the target is reached and we have no more state updates, we want to check to see if we need to reset.
564- if ( m_BufferQueue . Count == 0 && InterpolateState . TargetReached )
595+ if ( InterpolateState . TargetReached && m_BufferQueue . Count == 0 )
565596 {
566597 // When the delta between the time sent and the current tick latency time-window is greater than the max delta time
567598 // plus the minimum delta time (a rough estimate of time to wait before we consider rate of change equal to zero),
@@ -614,14 +645,6 @@ public void AddMeasurement(T newMeasurement, double sentTime)
614645 internal void AddMeasurement ( Transform parent , T newMeasurement , double sentTime )
615646 {
616647 m_NbItemsReceivedThisFrame ++ ;
617- var previousMeasurement = newMeasurement ;
618- // If enabled, convert everything to world space if in local space.
619- if ( ConvertTransformSpace ( parent ) )
620- {
621- // Keep everything in world space
622- newMeasurement = OnConvertTransformSpace ( parent , newMeasurement , false ) ;
623- }
624-
625648 // This situation can happen after a game is paused. When starting to receive again, the server will have sent a bunch of messages in the meantime
626649 // instead of going through thousands of value updates just to get a big teleport, we're giving up on interpolation and teleporting to the latest value
627650 if ( m_NbItemsReceivedThisFrame > k_BufferCountLimit )
@@ -633,7 +656,10 @@ internal void AddMeasurement(Transform parent, T newMeasurement, double sentTime
633656 // Reset to the new value but don't automatically add the measurement (prevents recursion)
634657 InternalReset ( parent , newMeasurement , sentTime , false ) ;
635658 m_LastMeasurementAddedTime = sentTime ;
636- m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount ) ;
659+ m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount )
660+ {
661+ MeasurementParent = parent ,
662+ } ;
637663 // Next line keeps renderTime above m_StartTimeConsumed. Fixes pause/unpause issues
638664 m_BufferQueue . Enqueue ( m_LastBufferedItemReceived ) ;
639665 }
@@ -644,7 +670,10 @@ internal void AddMeasurement(Transform parent, T newMeasurement, double sentTime
644670 if ( sentTime > m_LastMeasurementAddedTime || m_BufferCount == 0 )
645671 {
646672 m_BufferCount ++ ;
647- m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount ) ;
673+ m_LastBufferedItemReceived = new BufferedItem ( newMeasurement , sentTime , m_BufferCount )
674+ {
675+ MeasurementParent = parent ,
676+ } ;
648677 m_BufferQueue . Enqueue ( m_LastBufferedItemReceived ) ;
649678 m_LastMeasurementAddedTime = sentTime ;
650679 }
@@ -657,14 +686,7 @@ internal void AddMeasurement(Transform parent, T newMeasurement, double sentTime
657686 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
658687 public T GetInterpolatedValue ( )
659688 {
660- var currentValue = InterpolateState . CurrentValue ;
661- // If we are auto adjusting the value from world to local
662- if ( ConvertTransformSpace ( Parent ) )
663- {
664- // Convert to local space
665- currentValue = OnConvertTransformSpace ( Parent , currentValue , true ) ;
666- }
667- return currentValue ;
689+ return InterpolateState . CurrentValue ;
668690 }
669691
670692 /// <summary>
0 commit comments