diff --git a/com.unity.netcode.gameobjects/Runtime/Components/AnticipatedNetworkTransform.cs b/com.unity.netcode.gameobjects/Runtime/Components/AnticipatedNetworkTransform.cs index 9f0545fc6c..eb2abeb288 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/AnticipatedNetworkTransform.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/AnticipatedNetworkTransform.cs @@ -86,6 +86,8 @@ public struct TransformState private bool m_OutstandingAuthorityChange = false; + private NetworkManager m_NetworkManager; + #if UNITY_EDITOR private void Reset() { @@ -157,7 +159,7 @@ public bool ShouldReanticipate /// The anticipated position public void AnticipateMove(Vector3 newPosition) { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) + if (m_NetworkManager == null || m_NetworkManager.ShutdownInProgress || !m_NetworkManager.IsListening) { return; } @@ -170,7 +172,7 @@ public void AnticipateMove(Vector3 newPosition) m_PreviousAnticipatedTransform = m_AnticipatedTransform; - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; + m_LastAnticipaionCounter = m_NetworkManager.AnticipationSystem.AnticipationCounter; m_SmoothDuration = 0; m_CurrentSmoothTime = 0; @@ -183,7 +185,7 @@ public void AnticipateMove(Vector3 newPosition) /// The anticipated rotation public void AnticipateRotate(Quaternion newRotation) { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) + if (m_NetworkManager == null || m_NetworkManager.ShutdownInProgress || !m_NetworkManager.IsListening) { return; } @@ -196,7 +198,7 @@ public void AnticipateRotate(Quaternion newRotation) m_PreviousAnticipatedTransform = m_AnticipatedTransform; - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; + m_LastAnticipaionCounter = m_NetworkManager.AnticipationSystem.AnticipationCounter; m_SmoothDuration = 0; m_CurrentSmoothTime = 0; @@ -209,7 +211,7 @@ public void AnticipateRotate(Quaternion newRotation) /// The anticipated scale public void AnticipateScale(Vector3 newScale) { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) + if (m_NetworkManager == null || m_NetworkManager.ShutdownInProgress || !m_NetworkManager.IsListening) { return; } @@ -222,7 +224,7 @@ public void AnticipateScale(Vector3 newScale) m_PreviousAnticipatedTransform = m_AnticipatedTransform; - m_LastAnticipaionCounter = NetworkManager.AnticipationSystem.AnticipationCounter; + m_LastAnticipaionCounter = m_NetworkManager.AnticipationSystem.AnticipationCounter; m_SmoothDuration = 0; m_CurrentSmoothTime = 0; @@ -235,7 +237,7 @@ public void AnticipateScale(Vector3 newScale) /// The anticipated transform state public void AnticipateState(TransformState newState) { - if (NetworkManager.ShutdownInProgress || !NetworkManager.IsListening) + if (m_NetworkManager == null || m_NetworkManager.ShutdownInProgress || !m_NetworkManager.IsListening) { return; } @@ -264,7 +266,7 @@ private void ProcessSmoothing() if (m_CurrentSmoothTime < m_SmoothDuration) { - m_CurrentSmoothTime += NetworkManager.RealTimeProvider.DeltaTime; + m_CurrentSmoothTime += m_NetworkManager.RealTimeProvider.DeltaTime; var transform_ = transform; var pct = math.min(m_CurrentSmoothTime / m_SmoothDuration, 1f); @@ -397,8 +399,8 @@ protected internal override void InternalOnNetworkSessionSynchronized() ResetAnticipatedState(); m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); } } @@ -410,21 +412,23 @@ protected internal override void InternalOnNetworkSessionSynchronized() protected internal override void InternalOnNetworkPostSpawn() { base.InternalOnNetworkPostSpawn(); - if (!CanCommitToTransform && NetworkManager.IsConnectedClient && !SynchronizeState.IsSynchronizing) + if (!CanCommitToTransform && m_NetworkManager.IsConnectedClient && !SynchronizeState.IsSynchronizing) { m_OutstandingAuthorityChange = true; ApplyAuthoritativeState(); ResetAnticipatedState(); m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); } } /// public override void OnNetworkSpawn() { - if (NetworkManager.DistributedAuthorityMode) + m_NetworkManager = NetworkManager; + + if (m_NetworkManager.DistributedAuthorityMode) { Debug.LogWarning($"This component is not currently supported in distributed authority."); } @@ -441,8 +445,8 @@ public override void OnNetworkSpawn() ResetAnticipatedState(); m_AnticipatedObject = new AnticipatedObject { Transform = this }; - NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.RegisterForAnticipationEvents(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.AllAnticipatedObjects.Add(m_AnticipatedObject); } /// @@ -450,9 +454,9 @@ public override void OnNetworkDespawn() { if (m_AnticipatedObject != null) { - NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); m_AnticipatedObject = null; } ResetAnticipatedState(); @@ -465,9 +469,9 @@ public override void OnDestroy() { if (m_AnticipatedObject != null) { - NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); - NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.DeregisterForAnticipationEvents(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.AllAnticipatedObjects.Remove(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.ObjectsToReanticipate.Remove(m_AnticipatedObject); m_AnticipatedObject = null; } @@ -514,7 +518,7 @@ public void Smooth(TransformState from, TransformState to, float durationSeconds protected override void OnBeforeUpdateTransformState() { // this is called when new data comes from the server - m_LastAuthorityUpdateCounter = NetworkManager.AnticipationSystem.LastAnticipationAck; + m_LastAuthorityUpdateCounter = m_NetworkManager.AnticipationSystem.LastAnticipationAck; m_OutstandingAuthorityChange = true; } @@ -567,7 +571,7 @@ protected override void OnTransformUpdated() m_AnticipatedTransform = m_AuthoritativeTransform; ShouldReanticipate = true; - NetworkManager.AnticipationSystem.ObjectsToReanticipate.Add(m_AnticipatedObject); + m_NetworkManager.AnticipationSystem.ObjectsToReanticipate.Add(m_AnticipatedObject); } } } diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs index 2fe642162a..94b247b5cc 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs @@ -27,7 +27,7 @@ private void FlushMessages() foreach (var animationUpdate in m_SendAnimationUpdates) { - if (m_NetworkAnimator.NetworkManager.DistributedAuthorityMode) + if (m_NetworkAnimator.DistributedAuthorityMode) { m_NetworkAnimator.SendAnimStateRpc(animationUpdate.AnimationMessage); } @@ -41,7 +41,7 @@ private void FlushMessages() foreach (var sendEntry in m_SendParameterUpdates) { - if (m_NetworkAnimator.NetworkManager.DistributedAuthorityMode) + if (m_NetworkAnimator.DistributedAuthorityMode) { m_NetworkAnimator.SendParametersUpdateRpc(sendEntry.ParametersUpdateMessage); } @@ -54,7 +54,7 @@ private void FlushMessages() foreach (var sendEntry in m_SendTriggerUpdates) { - if (m_NetworkAnimator.NetworkManager.DistributedAuthorityMode) + if (m_NetworkAnimator.DistributedAuthorityMode) { m_NetworkAnimator.SendAnimTriggerRpc(sendEntry.AnimationTriggerMessage); } @@ -213,6 +213,10 @@ internal class TransitionStateinfo // [Layer][DestinationState][TransitionStateInfo] private Dictionary> m_DestinationStateToTransitioninfo = new Dictionary>(); + private NetworkManager m_NetworkManager; + + internal bool DistributedAuthorityMode; + /// /// Builds the m_DestinationStateToTransitioninfo lookup table /// @@ -509,7 +513,12 @@ internal bool IsServerAuthoritative() /// protected virtual bool OnIsServerAuthoritative() { - return NetworkManager ? !NetworkManager.DistributedAuthorityMode : true; + if (!m_NetworkManager) + { + return true; + } + + return !DistributedAuthorityMode; } private int[] m_TransitionHash; @@ -713,6 +722,10 @@ internal AnimationMessage GetAnimationMessage() /// public override void OnNetworkSpawn() { + // Save internal state references + m_NetworkManager = NetworkManager; + DistributedAuthorityMode = m_NetworkManager.DistributedAuthorityMode; + // If there is no assigned Animator then generate a server network warning (logged locally and if applicable on the server-host side as well). if (m_Animator == null) { @@ -963,7 +976,7 @@ internal void CheckForAnimatorChanges() if (m_Animator.runtimeAnimatorController == null) { - if (NetworkManager.LogLevel == LogLevel.Developer) + if (m_NetworkManager.LogLevel == LogLevel.Developer) { Debug.LogError($"[{GetType().Name}] Could not find an assigned {nameof(RuntimeAnimatorController)}! Cannot check {nameof(Animator)} for changes in state!"); } @@ -985,7 +998,7 @@ internal void CheckForAnimatorChanges() // Send an AnimationMessage only if there are dirty AnimationStates to send if (m_AnimationMessage.IsDirtyCount > 0) { - if (NetworkManager.DistributedAuthorityMode) + if (DistributedAuthorityMode) { SendAnimStateRpc(m_AnimationMessage); } @@ -998,9 +1011,9 @@ internal void CheckForAnimatorChanges() { // Just notify all remote clients and not the local server m_ClientSendList.Clear(); - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) + foreach (var clientId in m_NetworkManager.ConnectionManager.ConnectedClientIds) { - if (clientId == NetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId)) + if (clientId == m_NetworkManager.LocalClientId || !NetworkObject.Observers.Contains(clientId)) { continue; } @@ -1020,7 +1033,7 @@ private void SendParametersUpdate(ClientRpcParams clientRpcParams = default, boo { Parameters = m_ParameterWriter.ToArray() }; - if (NetworkManager.DistributedAuthorityMode) + if (DistributedAuthorityMode) { if (IsOwner) { @@ -1028,7 +1041,7 @@ private void SendParametersUpdate(ClientRpcParams clientRpcParams = default, boo } else { - Debug.LogError($"[{name}][Client-{NetworkManager.LocalClientId}] Attempting to send parameter updates but not the owner!"); + Debug.LogError($"[{name}][Client-{m_NetworkManager.LocalClientId}] Attempting to send parameter updates but not the owner!"); } } else @@ -1266,12 +1279,12 @@ internal void UpdateAnimationState(AnimationState animationState) // Cross fade from the current to the destination state for the transitions duration while starting at the server's current normalized time of the transition m_Animator.CrossFade(transitionStateInfo.DestinationState, transitionStateInfo.TransitionDuration, transitionStateInfo.Layer, 0.0f, animationState.NormalizedTime); } - else if (NetworkManager.LogLevel == LogLevel.Developer) + else if (m_NetworkManager.LogLevel == LogLevel.Developer) { NetworkLog.LogWarning($"Current State Hash ({currentState.fullPathHash}) != AnimationState.StateHash ({animationState.StateHash})"); } } - else if (NetworkManager.LogLevel == LogLevel.Developer) + else if (m_NetworkManager.LogLevel == LogLevel.Developer) { NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) sub-table does not contain destination state ({animationState.DestinationStateHash})!"); } @@ -1314,21 +1327,24 @@ private unsafe void SendParametersUpdateServerRpc(ParametersUpdateMessage parame return; } UpdateParameters(ref parametersUpdate); - if (NetworkManager.ConnectedClientsIds.Count > (IsHost ? 2 : 1)) + var connectedClientIds = m_NetworkManager.ConnectionManager.ConnectedClientIds; + if (connectedClientIds.Count <= (IsHost ? 2 : 1)) { - m_ClientSendList.Clear(); - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) + return; + } + + m_ClientSendList.Clear(); + foreach (var clientId in connectedClientIds) + { + if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId)) { - if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId)) - { - continue; - } - m_ClientSendList.Add(clientId); + continue; } - - m_ClientRpcParams.Send.TargetClientIds = m_ClientSendList; - m_NetworkAnimatorStateChangeHandler.SendParameterUpdate(parametersUpdate, m_ClientRpcParams); + m_ClientSendList.Add(clientId); } + + m_ClientRpcParams.Send.TargetClientIds = m_ClientSendList; + m_NetworkAnimatorStateChangeHandler.SendParameterUpdate(parametersUpdate, m_ClientRpcParams); } } @@ -1377,20 +1393,23 @@ private void SendAnimStateServerRpc(AnimationMessage animationMessage, ServerRpc UpdateAnimationState(animationState); } - if (NetworkManager.ConnectedClientsIds.Count > (IsHost ? 2 : 1)) + var connectedClientIds = m_NetworkManager.ConnectionManager.ConnectedClientIds; + if (connectedClientIds.Count <= (IsHost ? 2 : 1)) { - m_ClientSendList.Clear(); - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) + return; + } + + m_ClientSendList.Clear(); + foreach (var clientId in connectedClientIds) + { + if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId)) { - if (clientId == serverRpcParams.Receive.SenderClientId || clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId)) - { - continue; - } - m_ClientSendList.Add(clientId); + continue; } - m_ClientRpcParams.Send.TargetClientIds = m_ClientSendList; - m_NetworkAnimatorStateChangeHandler.SendAnimationUpdate(animationMessage, m_ClientRpcParams); + m_ClientSendList.Add(clientId); } + m_ClientRpcParams.Send.TargetClientIds = m_ClientSendList; + m_NetworkAnimatorStateChangeHandler.SendAnimationUpdate(animationMessage, m_ClientRpcParams); } } @@ -1416,10 +1435,10 @@ private void ProcessAnimStates(AnimationMessage animationMessage) { if (HasAuthority) { - if (NetworkManager.LogLevel == LogLevel.Developer) + if (m_NetworkManager.LogLevel == LogLevel.Developer) { - var hostOrOwner = NetworkManager.DistributedAuthorityMode ? "Owner" : "Host"; - var clientServerOrDAMode = NetworkManager.DistributedAuthorityMode ? "distributed authority" : "client-server"; + var hostOrOwner = DistributedAuthorityMode ? "Owner" : "Host"; + var clientServerOrDAMode = DistributedAuthorityMode ? "distributed authority" : "client-server"; NetworkLog.LogWarning($"Detected the {hostOrOwner} is sending itself animation updates in {clientServerOrDAMode} mode! Please report this issue."); } return; @@ -1443,7 +1462,7 @@ internal void SendAnimTriggerServerRpc(AnimationTriggerMessage animationTriggerM // Ignore if a non-owner sent this. if (serverRpcParams.Receive.SenderClientId != OwnerClientId) { - if (NetworkManager.LogLevel == LogLevel.Developer) + if (m_NetworkManager.LogLevel == LogLevel.Developer) { NetworkLog.LogWarning($"[Owner Authoritative] Detected the a non-authoritative client is sending the server animation trigger updates. If you recently changed ownership of the {name} object, then this could be the reason."); } @@ -1453,8 +1472,10 @@ internal void SendAnimTriggerServerRpc(AnimationTriggerMessage animationTriggerM // set the trigger locally on the server InternalSetTrigger(animationTriggerMessage.Hash, animationTriggerMessage.IsTriggerSet); + var connectedClientIds = m_NetworkManager.ConnectionManager.ConnectedClientIds; + m_ClientSendList.Clear(); - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) + foreach (var clientId in connectedClientIds) { if (clientId == NetworkManager.ServerClientId || !NetworkObject.Observers.Contains(clientId)) { @@ -1466,7 +1487,7 @@ internal void SendAnimTriggerServerRpc(AnimationTriggerMessage animationTriggerM { m_NetworkAnimatorStateChangeHandler.QueueTriggerUpdateToClient(animationTriggerMessage, m_ClientRpcParams); } - else if (NetworkManager.ConnectedClientsIds.Count > (IsHost ? 2 : 1)) + else if (connectedClientIds.Count > (IsHost ? 2 : 1)) { m_ClientSendList.Remove(serverRpcParams.Receive.SenderClientId); m_NetworkAnimatorStateChangeHandler.QueueTriggerUpdateToClient(animationTriggerMessage, m_ClientRpcParams); @@ -1531,12 +1552,12 @@ public void SetTrigger(int hash, bool setTrigger = true) // will happen when SendAnimTriggerClientRpc is called. For a client owner, we call the // SendAnimTriggerServerRpc and then trigger locally when running in owner authority mode. var animTriggerMessage = new AnimationTriggerMessage() { Hash = hash, IsTriggerSet = setTrigger }; - if (NetworkManager.DistributedAuthorityMode && HasAuthority) + if (DistributedAuthorityMode && HasAuthority) { m_NetworkAnimatorStateChangeHandler.QueueTriggerUpdateToClient(animTriggerMessage); InternalSetTrigger(hash, setTrigger); } - else if (!NetworkManager.DistributedAuthorityMode && (IsOwner || IsServer)) + else if (!DistributedAuthorityMode && (IsOwner || IsServer)) { if (IsServer) { diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs index 332694af7d..8b6954e283 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs @@ -3,7 +3,6 @@ using Unity.Collections; using UnityEngine; - namespace Unity.Netcode { /// @@ -87,7 +86,7 @@ internal FastBufferWriter __beginSendServerRpc(uint rpcMethodId, ServerRpcParams internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, ServerRpcParams serverRpcParams, RpcDelivery rpcDelivery) #pragma warning restore IDE1006 // restore naming rule violation check { - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; var serverRpcMessage = new ServerRpcMessage { Metadata = new RpcMetadata @@ -138,14 +137,14 @@ internal void __endSendServerRpc(ref FastBufferWriter bufferWriter, uint rpcMeth } else { - rpcWriteSize = NetworkManager.ConnectionManager.SendMessage(ref serverRpcMessage, networkDelivery, NetworkManager.ServerClientId); + rpcWriteSize = networkManager.ConnectionManager.SendMessage(ref serverRpcMessage, networkDelivery, NetworkManager.ServerClientId); } bufferWriter.Dispose(); #if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE if (__rpc_name_table[GetType()].TryGetValue(rpcMethodId, out var rpcMethodName)) { - NetworkManager.NetworkMetrics.TrackRpcSent( + networkManager.NetworkMetrics.TrackRpcSent( NetworkManager.ServerClientId, m_NetworkObject, rpcMethodName, @@ -173,7 +172,7 @@ internal FastBufferWriter __beginSendClientRpc(uint rpcMethodId, ClientRpcParams internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, ClientRpcParams clientRpcParams, RpcDelivery rpcDelivery) #pragma warning restore IDE1006 // restore naming rule violation check { - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; var clientRpcMessage = new ClientRpcMessage { Metadata = new RpcMetadata @@ -221,7 +220,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth NetworkLog.LogError(GenerateObserverErrorMessage(clientRpcParams, targetClientId)); } } - rpcWriteSize = NetworkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, in clientRpcParams.Send.TargetClientIds); + rpcWriteSize = m_NetworkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, in clientRpcParams.Send.TargetClientIds); } else if (clientRpcParams.Send.TargetClientIdsNativeArray != null) { @@ -238,7 +237,7 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth NetworkLog.LogError(GenerateObserverErrorMessage(clientRpcParams, targetClientId)); } } - rpcWriteSize = NetworkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, clientRpcParams.Send.TargetClientIdsNativeArray.Value); + rpcWriteSize = networkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, clientRpcParams.Send.TargetClientIdsNativeArray.Value); } else { @@ -246,12 +245,12 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth while (observerEnumerator.MoveNext()) { // Skip over the host - if (IsHost && observerEnumerator.Current == NetworkManager.LocalClientId) + if (IsHost && observerEnumerator.Current == networkManager.LocalClientId) { shouldInvokeLocally = true; continue; } - rpcWriteSize = NetworkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, observerEnumerator.Current); + rpcWriteSize = networkManager.ConnectionManager.SendMessage(ref clientRpcMessage, networkDelivery, observerEnumerator.Current); } } @@ -349,7 +348,7 @@ internal void __endSendRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, NetworkBehaviourId = NetworkBehaviourId, NetworkRpcMethodId = rpcMethodId, }, - SenderClientId = NetworkManager.LocalClientId, + SenderClientId = m_NetworkManager.LocalClientId, WriteBuffer = bufferWriter }; @@ -361,7 +360,7 @@ internal void __endSendRpc(ref FastBufferWriter bufferWriter, uint rpcMethodId, networkDelivery = NetworkDelivery.ReliableFragmentedSequenced; break; case RpcDelivery.Unreliable: - if (bufferWriter.Length > NetworkManager.MessageManager.NonFragmentedMessageMaxSize) + if (bufferWriter.Length > m_NetworkManager.MessageManager.NonFragmentedMessageMaxSize) { throw new OverflowException("RPC parameters are too large for unreliable delivery."); } @@ -436,6 +435,8 @@ internal string GenerateObserverErrorMessage(ClientRpcParams clientRpcParams, ul return $"Sending ClientRpc to non-observer! {containerNameHoldingId} contains clientId {targetClientId} that is not an observer!"; } + private NetworkManager m_NetworkManager; + /// /// Gets the NetworkManager that owns this NetworkBehaviour instance. /// See `NetworkObject` note for how there is a chicken/egg problem when not initialized. @@ -444,9 +445,14 @@ public NetworkManager NetworkManager { get { + if (m_NetworkManager != null) + { + return m_NetworkManager; + } + if (NetworkObject?.NetworkManager != null) { - return NetworkObject?.NetworkManager; + return NetworkObject.NetworkManager; } return NetworkManager.Singleton; @@ -469,7 +475,7 @@ public NetworkManager NetworkManager /// . /// #pragma warning restore IDE0001 - public RpcTarget RpcTarget => NetworkManager.RpcTarget; + public RpcTarget RpcTarget { get; private set; } /// /// If a NetworkObject is assigned, returns whether the NetworkObject @@ -543,21 +549,13 @@ public bool IsSessionOwner internal bool IsBehaviourEditable() { - if (!m_NetworkObject) + if (!m_NetworkObject || !m_NetworkManager || !m_NetworkManager.IsListening) { return true; } - if (!m_NetworkObject.NetworkManager) - { - return true; - } - - var networkManager = m_NetworkObject.NetworkManager; - // Only the authority can MODIFY. So allow modification if network is either not running or we are the authority. - return !networkManager.IsListening || - ((networkManager.DistributedAuthorityMode && m_NetworkObject.IsOwner) || (!networkManager.DistributedAuthorityMode && networkManager.IsServer)); + return HasAuthority; } internal void SetNetworkObject(NetworkObject networkObject) @@ -598,7 +596,7 @@ public NetworkObject NetworkObject // or NetworkBehaviour.IsSpawned (i.e. to early exit if not spawned) which, in turn, could generate several Warning messages // per spawned NetworkObject. Checking for ShutdownInProgress prevents these unnecessary LogWarning messages. // We must check IsSpawned, otherwise a warning will be logged under certain valid conditions (see OnDestroy) - if (IsSpawned && m_NetworkObject == null && (NetworkManager.Singleton == null || !NetworkManager.Singleton.ShutdownInProgress)) + if (IsSpawned && m_NetworkObject == null && (m_NetworkManager == null || !m_NetworkManager.ShutdownInProgress)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { @@ -615,7 +613,7 @@ public NetworkObject NetworkObject /// public bool HasNetworkObject => NetworkObject != null; - private NetworkObject m_NetworkObject = null; + private NetworkObject m_NetworkObject; /// /// Gets the NetworkId of the NetworkObject that owns this NetworkBehaviour instance. @@ -655,7 +653,7 @@ protected NetworkBehaviour GetNetworkBehaviour(ushort behaviourId) internal void UpdateNetworkProperties() { var networkObject = m_NetworkObject; - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; // Set identification related properties NetworkObjectId = networkObject.NetworkObjectId; @@ -763,6 +761,8 @@ public virtual void OnNetworkPreDespawn() { } internal void NetworkPreSpawn(ref NetworkManager networkManager, NetworkObject networkObject) { m_NetworkObject = networkObject; + m_NetworkManager = networkManager; + UpdateNetworkProperties(); try @@ -1106,7 +1106,7 @@ internal void NetworkVariableUpdate(ulong targetClientId, bool forceSend = false } // Getting these ahead of time actually improves performance - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; var networkObject = m_NetworkObject; var behaviourIndex = networkObject.GetNetworkBehaviourOrderIndex(this); var messageManager = networkManager.MessageManager; @@ -1193,7 +1193,7 @@ private bool CouldHaveDirtyNetworkVariables() } // If it's dirty but can't be sent yet, we have to keep monitoring it until one of the // conditions blocking its send changes. - NetworkManager.BehaviourUpdater.AddForUpdate(m_NetworkObject); + m_NetworkManager.BehaviourUpdater.AddForUpdate(m_NetworkObject); } } @@ -1259,7 +1259,7 @@ internal void MarkOwnerReadDirtyAndCheckOwnerWriteIsDirty() internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClientId) { // Create any values that require accessing the NetworkManager locally (it is expensive to access it in NetworkBehaviour) - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety; foreach (var field in NetworkVariableFields) @@ -1313,7 +1313,7 @@ internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClie internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId) { // Stack cache any values that requires accessing the NetworkManager (it is expensive to access it in NetworkBehaviour) - var networkManager = NetworkManager; + var networkManager = m_NetworkManager; var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety; foreach (var field in NetworkVariableFields) @@ -1358,7 +1358,7 @@ internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId) var totalBytesRead = reader.Position - readStartPos; if (totalBytesRead != expectedBytesToRead) { - if (NetworkManager.LogLevel <= LogLevel.Normal) + if (networkManager.LogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{field.Name}] NetworkVariable read {totalBytesRead} bytes but was expected to read {expectedBytesToRead} bytes during synchronization deserialization!"); } @@ -1375,7 +1375,7 @@ internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId) /// The NetworkObject instance if found, null if no object exists with the specified networkId protected NetworkObject GetNetworkObject(ulong networkId) { - return NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(networkId, out NetworkObject networkObject) ? networkObject : null; + return m_NetworkManager.SpawnManager.SpawnedObjects.GetValueOrDefault(networkId); } /// @@ -1456,10 +1456,10 @@ internal bool Synchronize(ref BufferSerializer serializer, ulong targetCli catch (Exception ex) { threwException = true; - if (NetworkManager.LogLevel <= LogLevel.Normal) + if (m_NetworkManager.LogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{name} threw an exception during synchronization serialization, this {nameof(NetworkBehaviour)} is being skipped and will not be synchronized!"); - if (NetworkManager.LogLevel == LogLevel.Developer) + if (m_NetworkManager.LogLevel == LogLevel.Developer) { NetworkLog.LogError($"{ex.Message}\n {ex.StackTrace}"); } @@ -1503,10 +1503,10 @@ internal bool Synchronize(ref BufferSerializer serializer, ulong targetCli } catch (Exception ex) { - if (NetworkManager.LogLevel <= LogLevel.Normal) + if (m_NetworkManager.LogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{name} threw an exception during synchronization deserialization, this {nameof(NetworkBehaviour)} is being skipped and will not be synchronized!"); - if (NetworkManager.LogLevel == LogLevel.Developer) + if (m_NetworkManager.LogLevel == LogLevel.Developer) { NetworkLog.LogError($"{ex.Message}\n {ex.StackTrace}"); } @@ -1517,7 +1517,7 @@ internal bool Synchronize(ref BufferSerializer serializer, ulong targetCli var totalBytesRead = reader.Position - positionBeforeSynchronize; if (totalBytesRead != expectedBytesToRead) { - if (NetworkManager.LogLevel <= LogLevel.Normal) + if (m_NetworkManager.LogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{name} read {totalBytesRead} bytes but was expected to read {expectedBytesToRead} bytes during synchronization deserialization! This {nameof(NetworkBehaviour)}({GetType().Name})is being skipped and will not be synchronized!"); }