@@ -1477,6 +1477,8 @@ internal bool SynchronizeScale
14771477 /// This field doesn't auto-synchronize with non-authority clients if changed on the authority instance during runtime (so you should apply this setting in-Editor).
14781478 /// Read the NetworkTransform documentation for more information and to avoid improper use.
14791479 /// </remarks>
1480+ [ Tooltip ( "When enabled, NetworkTransform controls world or local space settings while also providing smooth parenting transitions." +
1481+ "When disabled, world or local space settings have to be adjusted by script or in the inspector view." ) ]
14801482 public bool SwitchTransformSpaceWhenParented = false ;
14811483
14821484 /// <summary>
@@ -2128,7 +2130,7 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, ref Tra
21282130 networkState . IsSynchronizing = isSynchronization ;
21292131
21302132 // Check for parenting when synchronizing and/or teleporting
2131- if ( isSynchronization || networkState . IsTeleportingNextFrame )
2133+ if ( isSynchronization || networkState . IsTeleportingNextFrame || forceState )
21322134 {
21332135 // This all has to do with complex nested hierarchies and how it impacts scale
21342136 // when set for the first time or teleporting and depends upon whether the
@@ -3495,6 +3497,12 @@ protected virtual void Awake()
34953497 m_RotationInterpolator = new BufferedLinearInterpolatorQuaternion ( ) ;
34963498 m_PositionInterpolator = new BufferedLinearInterpolatorVector3 ( ) ;
34973499 m_ScaleInterpolator = new BufferedLinearInterpolatorVector3 ( ) ;
3500+
3501+ // Always start in world space until spawned and initialized.
3502+ if ( SwitchTransformSpaceWhenParented )
3503+ {
3504+ InLocalSpace = false ;
3505+ }
34983506 }
34993507
35003508 /// <inheritdoc/>
@@ -4446,9 +4454,10 @@ internal void TransformStateUpdate(ulong senderId, bool isParentingDirective)
44464454 /// </summary>
44474455 internal void ParentingUpdate ( NetworkObject parent , bool worldPositionStays )
44484456 {
4457+ InLocalSpace = parent ;
44494458 // Super-edge case when spawning an object with ownership and then immeidatley
44504459 // parenting. If so, update the current position and rotation values.
4451- if ( ! CanCommitToTransform && IsServer )
4460+ if ( ! CanCommitToTransform && IsServer && InLocalSpace )
44524461 {
44534462 m_InternalCurrentPosition = transform . localPosition ;
44544463 m_InternalCurrentRotation = transform . localRotation ;
@@ -4457,39 +4466,36 @@ internal void ParentingUpdate(NetworkObject parent, bool worldPositionStays)
44574466 m_HalfPositionState . UpdateFrom ( ref m_InternalCurrentPosition , m_CachedNetworkManager . LocalTime . Tick ) ;
44584467 }
44594468 }
4460- InLocalSpace = parent ;
44614469 m_OutboundMessage . SetParent ( new NetworkObjectReference ( parent ) , worldPositionStays ) ;
44624470
44634471 var transformToCommit = transform ;
44644472 CheckForStateChange ( ref m_LocalAuthoritativeNetworkState , ref transformToCommit , false , forceState : true ) ;
44654473 UpdateTransformState ( ) ;
44664474 // Reset the parent state for next state update that might not have a parent directive included
44674475 m_OutboundMessage . ResetParent ( ) ;
4476+ m_PreviousParent = parent ;
44684477 }
44694478
44704479 private NetworkObject m_PreviousParent ;
44714480
44724481 internal void UpdateParenting ( NetworkObjectReference parent , bool worldPositionStays )
44734482 {
44744483 var parentObject = ( NetworkObject ) null ;
4475- var removeParent = ! parent . TryGet ( out parentObject ) ;
4484+ var isParenting = parent . TryGet ( out parentObject ) ;
4485+
4486+ if ( m_PreviousParent && InboundState . IsParented != isParenting )
4487+ {
4488+ Debug . LogError ( $ "[Client-{ NetworkManager . LocalClientId } ][{ name } ][Parenting Directive Mismatch] Inbound state " +
4489+ $ "{ nameof ( NetworkTransformState . IsParented ) } is { InboundState . IsParented } and isParenting is { isParenting } !") ;
4490+ }
4491+
44764492 // Parent
44774493 NetworkObject . AuthorityAppliedParenting = true ;
44784494 ulong ? parentObjectId = parentObject ? parentObject . NetworkObjectId : null ;
44794495 NetworkObject . SetNetworkParenting ( parentObjectId , worldPositionStays ) ;
4480- NetworkObject . ApplyNetworkParenting ( removeParent : removeParent ) ;
4481- if ( ! removeParent )
4496+ NetworkObject . ApplyNetworkParenting ( removeParent : ! isParenting ) ;
4497+ if ( isParenting )
44824498 {
4483- // Convert the world space transform values to the local space of the new transform
4484- if ( SynchronizePosition )
4485- {
4486- m_InternalCurrentPosition = parentObject . transform . InverseTransformPoint ( transform . position ) ;
4487- }
4488- if ( SynchronizeRotation )
4489- {
4490- m_InternalCurrentRotation = Quaternion . Inverse ( parentObject . transform . rotation ) * m_InternalCurrentRotation ;
4491- }
4492-
44934499 // If we had a previous parent...
44944500 if ( m_PreviousParent && InLocalSpace )
44954501 {
@@ -4505,8 +4511,21 @@ internal void UpdateParenting(NetworkObjectReference parent, bool worldPositionS
45054511 m_RotationInterpolator . ConvertTransformSpace ( m_PreviousParent . transform , false ) ;
45064512 }
45074513 }
4508- InLocalSpace = true ;
4509- // Convert the world space values of the interpolators to local space
4514+ else if ( m_PreviousParent && ! InLocalSpace )
4515+ {
4516+ Debug . LogError ( $ "[Client-{ NetworkManager . LocalClientId } ][{ name } ][Parenting Directive Mismatch] { nameof ( m_PreviousParent ) } is not null but { nameof ( InLocalSpace ) } is { InLocalSpace } !") ;
4517+ }
4518+
4519+ // Convert the world space transform values to the local space of the new transform
4520+ if ( SynchronizePosition )
4521+ {
4522+ m_InternalCurrentPosition = parentObject . transform . InverseTransformPoint ( transform . position ) ;
4523+ }
4524+ if ( SynchronizeRotation )
4525+ {
4526+ m_InternalCurrentRotation = Quaternion . Inverse ( parentObject . transform . rotation ) * m_InternalCurrentRotation ;
4527+ }
4528+ // Convert the world space values of the interpolators to local space of the new parent
45104529 if ( SynchronizePosition )
45114530 {
45124531 m_PositionInterpolator . ConvertTransformSpace ( parentObject . transform , true ) ;
@@ -4516,10 +4535,11 @@ internal void UpdateParenting(NetworkObjectReference parent, bool worldPositionS
45164535 m_RotationInterpolator . ConvertTransformSpace ( parentObject . transform , true ) ;
45174536 }
45184537 m_PreviousParent = parentObject ;
4538+ // Always assure this is true
4539+ InLocalSpace = true ;
45194540 }
45204541 else if ( m_PreviousParent )
45214542 {
4522- InLocalSpace = false ;
45234543 // Convert everything back to world space values
45244544 if ( SynchronizePosition )
45254545 {
@@ -4528,13 +4548,15 @@ internal void UpdateParenting(NetworkObjectReference parent, bool worldPositionS
45284548 }
45294549 if ( SynchronizeRotation )
45304550 {
4531- m_InternalCurrentRotation = m_PreviousParent . transform . localRotation * m_InternalCurrentRotation ;
4551+ m_InternalCurrentRotation = m_PreviousParent . transform . localRotation * transform . localRotation ;
45324552 m_RotationInterpolator . ConvertTransformSpace ( m_PreviousParent . transform , false ) ;
45334553 }
45344554 m_PreviousParent = null ;
4555+ // Always assure this is false
4556+ InLocalSpace = false ;
45354557 }
45364558
4537- if ( UseHalfFloatPrecision )
4559+ if ( SynchronizePosition && UseHalfFloatPrecision )
45384560 {
45394561 m_HalfPositionState . UpdateFrom ( ref m_InternalCurrentPosition , m_CachedNetworkManager . LocalTime . Tick ) ;
45404562 }
0 commit comments