Skip to content

Commit 296b9f5

Browse files
noellie-velezEmandMNoelStephensUnity
authored
chore: Optimize NetworkTransform (#3907)
* Use cached `NetworkManager` instead of a field to avoid lazy instantiation overhead and improve performance * Convert `RegisterForTickUpdate` to non-static since static context was unnecessary and prevented use of cached `NetworkManager` * Cache `tickRate` to reduce repeated lookups * Remove redundant local `NetworkManager` variable in `RegisterForTickUpdate` for consistency * Add `networkObject.name` to `NetcodeTransformMessage` * Update changelog --------- Co-authored-by: Emma <emma.mcmillan@unity3d.com> Co-authored-by: Noel Stephens <noel.stephens@unity3d.com>
1 parent c242ca7 commit 296b9f5

File tree

3 files changed

+44
-41
lines changed

3 files changed

+44
-41
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ Additional documentation and release notes are available at [Multiplayer Documen
1212

1313

1414
### Changed
15-
- Improve performance of `NetworkBehavior`. (#3915)
15+
16+
- Improve performance of `NetworkBehaviour`. (#3915)
17+
- Improve performance of `NetworkTransform`. (#3907)
1618
- Improve performance of `NetworkRigidbodyBase`. (#3906)
1719
- Improve performance of `NetworkAnimator`. (#3905)
1820

com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,7 @@ internal bool SynchronizeScale
16211621
public bool CanCommitToTransform { get; protected set; }
16221622

16231623
/// <summary>
1624-
/// Internally used by <see cref="NetworkTransform"/> to keep track of the <see cref="NetworkManager"/> instance assigned to this
1624+
/// Internally used by <see cref="NetworkTransform"/> to keep track of the <see cref="NetworkManager"/> instance assigned to
16251625
/// this <see cref="NetworkBehaviour"/> derived class instance.
16261626
/// </summary>
16271627
protected NetworkManager m_CachedNetworkManager;
@@ -2136,9 +2136,8 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, bool is
21362136
// We compare against the NetworkTickSystem version since ServerTime is set when updating ticks
21372137
if (UseUnreliableDeltas && !isSynchronization && m_DeltaSynch && m_NextTickSync <= CurrentTick)
21382138
{
2139-
// TODO-CACHE: m_CachedNetworkManager.NetworkConfig.TickRate value
21402139
// Increment to the next frame synch tick position for this instance
2141-
m_NextTickSync += (int)m_CachedNetworkManager.NetworkConfig.TickRate;
2140+
m_NextTickSync += m_CachedTickRate;
21422141
// If we are teleporting, we do not need to send a frame synch for this tick slot
21432142
// as a "frame synch" really is effectively just a teleport.
21442143
isAxisSync = !flagStates.IsTeleportingNextFrame;
@@ -2606,7 +2605,7 @@ private void OnNetworkTick(bool isCalledFromParent = false)
26062605
}
26072606
else // If we are no longer authority, unsubscribe to the tick event
26082607
{
2609-
DeregisterForTickUpdate(this);
2608+
DeregisterForTickUpdate();
26102609
}
26112610
}
26122611
#endregion
@@ -3537,7 +3536,7 @@ private void ApplyPlayerTransformState()
35373536

35383537
/// <summary>
35393538
/// For dynamically spawned NetworkObjects, when the non-authority instance's client is already connected and
3540-
/// the SynchronizeState is still pending synchronization then we want to finalize the synchornization at this time.
3539+
/// the SynchronizeState is still pending synchronization then we want to finalize the synchronization at this time.
35413540
/// </summary>
35423541
protected internal override void InternalOnNetworkPostSpawn()
35433542
{
@@ -3550,7 +3549,7 @@ protected internal override void InternalOnNetworkPostSpawn()
35503549
// Then we want to:
35513550
// - Force the "IsSynchronizing" flag so the NetworkTransform has its state updated properly and runs through the initialization again.
35523551
// - Make sure the SynchronizingState is updated to the instantiated prefab's default flags/settings.
3553-
if (NetworkManager.IsServer && !NetworkManager.DistributedAuthorityMode && !IsOwner && !OnIsServerAuthoritative() && !SynchronizeState.IsSynchronizing)
3552+
if (m_CachedNetworkManager.IsServer && !m_CachedNetworkManager.DistributedAuthorityMode && !IsOwner && !OnIsServerAuthoritative() && !SynchronizeState.IsSynchronizing)
35543553
{
35553554
// Handle the first/root NetworkTransform slightly differently to have a sequenced synchronization of like authority nested NetworkTransform components
35563555
if (m_IsFirstNetworkTransform)
@@ -3578,7 +3577,7 @@ protected internal override void InternalOnNetworkPostSpawn()
35783577
}
35793578

35803579
// Standard non-authority synchronization is handled here
3581-
if (!CanCommitToTransform && NetworkManager.IsConnectedClient && SynchronizeState.IsSynchronizing)
3580+
if (!CanCommitToTransform && m_CachedNetworkManager.IsConnectedClient && SynchronizeState.IsSynchronizing)
35823581
{
35833582
NonAuthorityFinalizeSynchronization();
35843583
}
@@ -3620,9 +3619,14 @@ protected virtual void Awake()
36203619
CachedTransform = transform;
36213620
}
36223621

3622+
private NetworkObject m_CachedNetworkObject;
3623+
private int m_CachedTickRate;
3624+
36233625
internal override void InternalOnNetworkPreSpawn(ref NetworkManager networkManager)
36243626
{
36253627
m_CachedNetworkManager = networkManager;
3628+
m_CachedNetworkObject = NetworkObject;
3629+
m_CachedTickRate = (int)networkManager.NetworkConfig.TickRate;
36263630
CachedTransform = transform;
36273631
base.InternalOnNetworkPreSpawn(ref networkManager);
36283632
}
@@ -3631,14 +3635,14 @@ internal override void InternalOnNetworkPreSpawn(ref NetworkManager networkManag
36313635
public override void OnNetworkSpawn()
36323636
{
36333637
m_ParentedChildren.Clear();
3634-
m_CachedNetworkManager = NetworkManager;
36353638

36363639
Initialize();
36373640

36383641
if (CanCommitToTransform && !SwitchTransformSpaceWhenParented)
36393642
{
36403643
SetState(GetSpaceRelativePosition(), GetSpaceRelativeRotation(), GetScale(), false);
36413644
}
3645+
base.OnNetworkSpawn();
36423646
}
36433647

36443648
private void CleanUpOnDestroyOrDespawn()
@@ -3651,10 +3655,10 @@ private void CleanUpOnDestroyOrDespawn()
36513655
#endif
36523656
if (m_CachedNetworkObject != null)
36533657
{
3654-
NetworkManager?.NetworkTransformRegistration(m_CachedNetworkObject, forUpdate, false);
3658+
m_CachedNetworkManager?.NetworkTransformRegistration(m_CachedNetworkObject, forUpdate, false);
36553659
}
36563660

3657-
DeregisterForTickUpdate(this);
3661+
DeregisterForTickUpdate();
36583662
CanCommitToTransform = false;
36593663
}
36603664

@@ -3697,7 +3701,7 @@ protected virtual void OnInitialize(ref NetworkVariable<NetworkTransformState> r
36973701
/// </summary>
36983702
private void ResetInterpolatedStateToCurrentAuthoritativeState()
36993703
{
3700-
var serverTime = NetworkManager.ServerTime.Time;
3704+
var serverTime = m_CachedNetworkManager.ServerTime.Time;
37013705
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
37023706
var position = m_UseRigidbodyForMotion ? m_NetworkRigidbodyInternal.GetPosition() : GetSpaceRelativePosition();
37033707
var rotation = m_UseRigidbodyForMotion ? m_NetworkRigidbodyInternal.GetRotation() : GetSpaceRelativeRotation();
@@ -3717,9 +3721,9 @@ private void ResetInterpolatedStateToCurrentAuthoritativeState()
37173721

37183722
m_ScaleInterpolator.ResetTo(transform.parent, transform.localScale, serverTime);
37193723
}
3720-
private NetworkObject m_CachedNetworkObject;
3724+
37213725
/// <summary>
3722-
/// The internal initialzation method to allow for internal API adjustments
3726+
/// The internal initialization method to allow for internal API adjustments
37233727
/// </summary>
37243728
/// <param name="isOwnershipChange"></param>
37253729
private void InternalInitialization(bool isOwnershipChange = false)
@@ -3728,10 +3732,9 @@ private void InternalInitialization(bool isOwnershipChange = false)
37283732
{
37293733
return;
37303734
}
3731-
m_CachedNetworkObject = NetworkObject;
37323735

37333736
// Determine if this is the first NetworkTransform in the associated NetworkObject's list
3734-
m_IsFirstNetworkTransform = NetworkObject.NetworkTransforms[0] == this;
3737+
m_IsFirstNetworkTransform = m_CachedNetworkObject.NetworkTransforms[0] == this;
37353738

37363739
if (m_CachedNetworkManager && m_CachedNetworkManager.DistributedAuthorityMode)
37373740
{
@@ -3755,9 +3758,9 @@ private void InternalInitialization(bool isOwnershipChange = false)
37553758
var currentPosition = GetSpaceRelativePosition();
37563759
var currentRotation = GetSpaceRelativeRotation();
37573760

3758-
if (NetworkManager.DistributedAuthorityMode)
3761+
if (m_CachedNetworkManager.DistributedAuthorityMode)
37593762
{
3760-
RegisterNetworkManagerForTickUpdate(NetworkManager);
3763+
RegisterNetworkManagerForTickUpdate(m_CachedNetworkManager);
37613764
}
37623765

37633766
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
@@ -3793,7 +3796,7 @@ private void InternalInitialization(bool isOwnershipChange = false)
37933796
m_InternalCurrentPosition = currentPosition;
37943797
m_LastStateTargetPosition = currentPosition;
37953798

3796-
RegisterForTickUpdate(this);
3799+
RegisterForTickUpdate();
37973800

37983801
if (UseHalfFloatPrecision && isOwnershipChange && !IsServerAuthoritative() && Interpolate)
37993802
{
@@ -3813,7 +3816,7 @@ private void InternalInitialization(bool isOwnershipChange = false)
38133816
// Non-authority needs to be added to updates for interpolation and applying state purposes
38143817
m_CachedNetworkManager.NetworkTransformRegistration(NetworkObject, forUpdate, true);
38153818
// Remove this instance from the tick update
3816-
DeregisterForTickUpdate(this);
3819+
DeregisterForTickUpdate();
38173820
ResetInterpolatedStateToCurrentAuthoritativeState();
38183821
m_InternalCurrentPosition = currentPosition;
38193822
m_LastStateTargetPosition = currentPosition;
@@ -3941,7 +3944,7 @@ internal override void InternalOnNetworkObjectParentChanged(NetworkObject parent
39413944
if (LastTickSync == m_LocalAuthoritativeNetworkState.GetNetworkTick())
39423945
{
39433946
m_InternalCurrentPosition = m_LastStateTargetPosition = GetSpaceRelativePosition();
3944-
m_PositionInterpolator.ResetTo(m_PositionInterpolator.Parent, m_InternalCurrentPosition, NetworkManager.ServerTime.Time);
3947+
m_PositionInterpolator.ResetTo(m_PositionInterpolator.Parent, m_InternalCurrentPosition, m_CachedNetworkManager.ServerTime.Time);
39453948
if (InLocalSpace)
39463949
{
39473950
transform.localPosition = m_InternalCurrentPosition;
@@ -3973,7 +3976,7 @@ internal override void InternalOnNetworkObjectParentChanged(NetworkObject parent
39733976
{
39743977
m_InternalCurrentRotation = GetSpaceRelativeRotation();
39753978
m_TargetRotation = m_InternalCurrentRotation.eulerAngles;
3976-
m_RotationInterpolator.ResetTo(m_RotationInterpolator.Parent, m_InternalCurrentRotation, NetworkManager.ServerTime.Time);
3979+
m_RotationInterpolator.ResetTo(m_RotationInterpolator.Parent, m_InternalCurrentRotation, m_CachedNetworkManager.ServerTime.Time);
39773980
if (InLocalSpace)
39783981
{
39793982
transform.localRotation = m_InternalCurrentRotation;
@@ -4596,7 +4599,7 @@ internal void TransformStateUpdate()
45964599
{
45974600
// TODO: Investigate where this state should be applied or just discarded.
45984601
// For now, discard the state if we assumed ownership.
4599-
// Debug.Log($"[Client-{NetworkManager.LocalClientId}] Ignoring inbound update from Client-{0} and parentUpdated:{isParentingDirective}!");
4602+
// Debug.Log($"[Client-{m_CachedNetworkManager.LocalClientId}] Ignoring inbound update from Client-{0} and parentUpdated:{isParentingDirective}!");
46004603
return;
46014604
}
46024605
// Store the previous/old state
@@ -4653,17 +4656,17 @@ private void UpdateTransformState()
46534656
{
46544657
continue;
46554658
}
4656-
if (!NetworkObject.Observers.Contains(clientId))
4659+
if (!m_CachedNetworkObject.Observers.Contains(clientId))
46574660
{
46584661
continue;
46594662
}
4660-
NetworkManager.MessageManager.SendMessage(ref m_OutboundMessage, networkDelivery, clientId);
4663+
m_CachedNetworkManager.MessageManager.SendMessage(ref m_OutboundMessage, networkDelivery, clientId);
46614664
}
46624665
}
46634666
else
46644667
{
46654668
// Clients (owner authoritative) send messages to the server-host
4666-
NetworkManager.MessageManager.SendMessage(ref m_OutboundMessage, networkDelivery, NetworkManager.ServerClientId);
4669+
m_CachedNetworkManager.MessageManager.SendMessage(ref m_OutboundMessage, networkDelivery, NetworkManager.ServerClientId);
46674670
}
46684671
m_LocalAuthoritativeNetworkState.LastSerializedSize = m_OutboundMessage.BytesWritten;
46694672
}
@@ -4802,7 +4805,7 @@ public NetworkTransformTickRegistration(NetworkManager networkManager)
48024805
internal void RegisterForTickSynchronization()
48034806
{
48044807
s_TickSynchPosition++;
4805-
m_NextTickSync = NetworkManager.ServerTime.Tick + (s_TickSynchPosition % (int)NetworkManager.NetworkConfig.TickRate);
4808+
m_NextTickSync = m_CachedNetworkManager.ServerTime.Tick + (s_TickSynchPosition % m_CachedTickRate);
48064809
}
48074810

48084811
private static void RegisterNetworkManagerForTickUpdate(NetworkManager networkManager)
@@ -4818,36 +4821,34 @@ private static void RegisterNetworkManagerForTickUpdate(NetworkManager networkMa
48184821
/// If a NetworkTransformTickRegistration has not yet been registered for the NetworkManager
48194822
/// instance, then create an entry.
48204823
/// </summary>
4821-
/// <param name="networkTransform"></param>
4822-
private static void RegisterForTickUpdate(NetworkTransform networkTransform)
4824+
private void RegisterForTickUpdate()
48234825
{
48244826

4825-
if (!networkTransform.NetworkManager.DistributedAuthorityMode && !s_NetworkTickRegistration.ContainsKey(networkTransform.NetworkManager))
4827+
if (!m_CachedNetworkManager.DistributedAuthorityMode && !s_NetworkTickRegistration.ContainsKey(m_CachedNetworkManager))
48264828
{
4827-
s_NetworkTickRegistration.Add(networkTransform.NetworkManager, new NetworkTransformTickRegistration(networkTransform.NetworkManager));
4829+
s_NetworkTickRegistration.Add(m_CachedNetworkManager, new NetworkTransformTickRegistration(m_CachedNetworkManager));
48284830
}
48294831

4830-
networkTransform.RegisterForTickSynchronization();
4831-
s_NetworkTickRegistration[networkTransform.NetworkManager].NetworkTransforms.Add(networkTransform);
4832+
RegisterForTickSynchronization();
4833+
s_NetworkTickRegistration[m_CachedNetworkManager].NetworkTransforms.Add(this);
48324834
}
48334835

48344836
/// <summary>
48354837
/// If a NetworkTransformTickRegistration exists for the NetworkManager instance, then this will
48364838
/// remove the NetworkTransform instance from the single tick update entry point.
48374839
/// </summary>
4838-
/// <param name="networkTransform"></param>
4839-
private static void DeregisterForTickUpdate(NetworkTransform networkTransform)
4840+
private void DeregisterForTickUpdate()
48404841
{
4841-
if (networkTransform.NetworkManager == null)
4842+
if (m_CachedNetworkManager == null)
48424843
{
48434844
return;
48444845
}
4845-
if (s_NetworkTickRegistration.ContainsKey(networkTransform.NetworkManager))
4846+
if (s_NetworkTickRegistration.ContainsKey(m_CachedNetworkManager))
48464847
{
4847-
s_NetworkTickRegistration[networkTransform.NetworkManager].NetworkTransforms.Remove(networkTransform);
4848-
if (!networkTransform.NetworkManager.DistributedAuthorityMode && s_NetworkTickRegistration[networkTransform.NetworkManager].NetworkTransforms.Count == 0)
4848+
s_NetworkTickRegistration[m_CachedNetworkManager].NetworkTransforms.Remove(this);
4849+
if (!m_CachedNetworkManager.DistributedAuthorityMode && s_NetworkTickRegistration[m_CachedNetworkManager].NetworkTransforms.Count == 0)
48494850
{
4850-
var registrationEntry = s_NetworkTickRegistration[networkTransform.NetworkManager];
4851+
var registrationEntry = s_NetworkTickRegistration[m_CachedNetworkManager];
48514852
registrationEntry.Remove();
48524853
}
48534854
}

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkTransformMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
106106
var transform = networkObject.ChildNetworkBehaviours[networkBehaviourId] as NetworkTransform;
107107
if (transform == null)
108108
{
109-
Debug.LogError($"[{nameof(NetworkTransformMessage)}][Invalid] Targeted {nameof(NetworkTransform)}, {nameof(NetworkBehaviour.NetworkBehaviourId)} ({networkBehaviourId}), does not exist! Make sure you are not spawning {nameof(NetworkObject)}s with disabled {nameof(GameObject)}s that have {nameof(NetworkBehaviour)} components on them.");
109+
Debug.LogError($"[{nameof(NetworkTransformMessage)}][Invalid] Targeted {nameof(NetworkTransform)}, {nameof(NetworkBehaviour.NetworkBehaviourId)} ({networkBehaviourId}), does not exist on {networkObject.name}! Make sure you are not spawning {nameof(NetworkObject)}s with disabled {nameof(GameObject)}s that have {nameof(NetworkBehaviour)} components on them.");
110110
return false;
111111
}
112112

0 commit comments

Comments
 (0)