@@ -306,6 +306,15 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
306
306
/// Whether or not z component of position will be replicated
307
307
/// </summary>
308
308
public bool SyncPositionZ = true ;
309
+
310
+ private bool SynchronizePosition
311
+ {
312
+ get
313
+ {
314
+ return SyncPositionX || SyncPositionY || SyncPositionZ ;
315
+ }
316
+ }
317
+
309
318
/// <summary>
310
319
/// Whether or not x component of rotation will be replicated
311
320
/// </summary>
@@ -318,6 +327,15 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
318
327
/// Whether or not z component of rotation will be replicated
319
328
/// </summary>
320
329
public bool SyncRotAngleZ = true ;
330
+
331
+ private bool SynchronizeRotation
332
+ {
333
+ get
334
+ {
335
+ return SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ ;
336
+ }
337
+ }
338
+
321
339
/// <summary>
322
340
/// Whether or not x component of scale will be replicated
323
341
/// </summary>
@@ -331,6 +349,15 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
331
349
/// </summary>
332
350
public bool SyncScaleZ = true ;
333
351
352
+
353
+ private bool SynchronizeScale
354
+ {
355
+ get
356
+ {
357
+ return SyncScaleX || SyncScaleY || SyncScaleZ ;
358
+ }
359
+ }
360
+
334
361
/// <summary>
335
362
/// The current position threshold value
336
363
/// Any changes to the position that exceeds the current threshold value will be replicated
@@ -352,7 +379,6 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
352
379
/// </summary>
353
380
public float ScaleThreshold = ScaleThresholdDefault ;
354
381
355
-
356
382
/// <summary>
357
383
/// Sets whether the transform should be treated as local (true) or world (false) space.
358
384
/// </summary>
@@ -651,6 +677,11 @@ private void ApplyAuthoritativeState()
651
677
// InLocalSpace Read:
652
678
InLocalSpace = networkState . InLocalSpace ;
653
679
680
+ // NOTE ABOUT INTERPOLATING AND BELOW CODE:
681
+ // We always apply the interpolated state for any axis we are synchronizing even when the state has no deltas
682
+ // to properly extrapolate. Extrapolation is stopped on the non-authoritative side 1 tick after the original
683
+ // state was applied.
684
+
654
685
// Update the position values that were changed in this state update
655
686
if ( networkState . HasPositionX )
656
687
{
@@ -698,7 +729,7 @@ private void ApplyAuthoritativeState()
698
729
interpolatedRotAngles . z = isTeleporting || ! Interpolate ? networkState . RotAngleZ : eulerAngles . z ;
699
730
}
700
731
}
701
- else if ( Interpolate && SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ )
732
+ else if ( Interpolate && SynchronizeRotation )
702
733
{
703
734
var eulerAngles = m_RotationInterpolator . GetInterpolatedValue ( ) . eulerAngles ;
704
735
interpolatedRotAngles = eulerAngles ;
@@ -723,19 +754,31 @@ private void ApplyAuthoritativeState()
723
754
{
724
755
interpolatedScale . x = isTeleporting || ! Interpolate ? networkState . ScaleX : m_ScaleXInterpolator . GetInterpolatedValue ( ) ;
725
756
}
757
+ else if ( Interpolate && SyncScaleX )
758
+ {
759
+ interpolatedScale . x = m_ScaleXInterpolator . GetInterpolatedValue ( ) ;
760
+ }
726
761
727
762
if ( networkState . HasScaleY )
728
763
{
729
764
interpolatedScale . y = isTeleporting || ! Interpolate ? networkState . ScaleY : m_ScaleYInterpolator . GetInterpolatedValue ( ) ;
730
765
}
766
+ else if ( Interpolate && SyncScaleY )
767
+ {
768
+ interpolatedScale . y = m_ScaleYInterpolator . GetInterpolatedValue ( ) ;
769
+ }
731
770
732
771
if ( networkState . HasScaleZ )
733
772
{
734
773
interpolatedScale . z = isTeleporting || ! Interpolate ? networkState . ScaleZ : m_ScaleZInterpolator . GetInterpolatedValue ( ) ;
735
774
}
775
+ else if ( Interpolate && SyncScaleZ )
776
+ {
777
+ interpolatedScale . z = m_ScaleZInterpolator . GetInterpolatedValue ( ) ;
778
+ }
736
779
737
780
// Apply the new position
738
- if ( networkState . HasPositionChange || Interpolate && ( SyncPositionX || SyncPositionY || SyncPositionZ ) )
781
+ if ( networkState . HasPositionChange || Interpolate && SynchronizePosition )
739
782
{
740
783
if ( InLocalSpace )
741
784
{
@@ -748,7 +791,7 @@ private void ApplyAuthoritativeState()
748
791
}
749
792
750
793
// Apply the new rotation
751
- if ( networkState . HasRotAngleChange || Interpolate && ( SyncRotAngleX || SyncRotAngleY || SyncRotAngleZ ) )
794
+ if ( networkState . HasRotAngleChange || Interpolate && SynchronizeRotation )
752
795
{
753
796
if ( InLocalSpace )
754
797
{
@@ -761,7 +804,7 @@ private void ApplyAuthoritativeState()
761
804
}
762
805
763
806
// Apply the new scale
764
- if ( networkState . HasScaleChange || Interpolate && ( SyncScaleX || SyncScaleY || SyncScaleZ ) )
807
+ if ( networkState . HasScaleChange || Interpolate && SynchronizeScale )
765
808
{
766
809
transform . localScale = interpolatedScale ;
767
810
}
@@ -990,18 +1033,25 @@ public void SetMaxInterpolationBound(float maxInterpolationBound)
990
1033
m_ScaleZInterpolator . MaxInterpolationBound = maxInterpolationBound ;
991
1034
}
992
1035
1036
+ /// <summary>
1037
+ /// Create interpolators when first instantiated to avoid memory allocations if the
1038
+ /// associated NetworkObject persists (i.e. despawned but not destroyed or pools)
1039
+ /// </summary>
993
1040
private void Awake ( )
994
1041
{
995
- // we only want to create our interpolators during Awake so that, when pooled, we do not create tons
996
- // of gc thrash each time objects wink out and are re-used
1042
+ // Rotation is a single Quaternion since each Euler axis will affect the quaternion's final value
1043
+ m_RotationInterpolator = new BufferedLinearInterpolatorQuaternion ( ) ;
1044
+
1045
+ // All other interpolators are BufferedLinearInterpolatorFloats
997
1046
m_PositionXInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
998
1047
m_PositionYInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
999
1048
m_PositionZInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
1000
- m_RotationInterpolator = new BufferedLinearInterpolatorQuaternion ( ) ; // rotation is a single Quaternion since each euler axis will affect the quaternion's final value
1001
1049
m_ScaleXInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
1002
1050
m_ScaleYInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
1003
1051
m_ScaleZInterpolator = new BufferedLinearInterpolatorFloat ( ) ;
1004
1052
1053
+ // Used to quickly iteration over the BufferedLinearInterpolatorFloat
1054
+ // instances
1005
1055
if ( m_AllFloatInterpolators . Count == 0 )
1006
1056
{
1007
1057
m_AllFloatInterpolators . Add ( m_PositionXInterpolator ) ;
0 commit comments