diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index 311a3df650..2779d4cf73 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -340,17 +340,18 @@ private void CheckForInScenePlaced() internal bool HasParentNetworkObject(Transform transform) { - if (transform.parent != null) + var parent = transform.parent; + if (parent != null) { - var networkObject = transform.parent.GetComponent(); + var networkObject = parent.GetComponent(); if (networkObject != null && networkObject != this) { return true; } - if (transform.parent.parent != null) + if (m_CachedParent.parent != null) { - return HasParentNetworkObject(transform.parent); + return HasParentNetworkObject(parent); } } return false; @@ -364,7 +365,7 @@ internal bool HasParentNetworkObject(Transform transform) /// /// Useful to know if we should or should not send a message /// - internal bool HasRemoteObservers => !(Observers.Count == 0 || (Observers.Contains(NetworkManager.LocalClientId) && Observers.Count == 1)); + internal bool HasRemoteObservers => !(Observers.Count == 0 || (Observers.Contains(NetworkManagerOwner.LocalClientId) && Observers.Count == 1)); /// /// Distributed Authority Mode Only @@ -398,29 +399,33 @@ internal bool HasParentNetworkObject(Transform transform) /// Defaults to true, determines whether the will be destroyed. public void DeferDespawn(int tickOffset, bool destroy = true) { - if (!NetworkManager.DistributedAuthorityMode) + if (!IsSpawned) { - NetworkLog.LogError($"This method is only available in distributed authority mode."); + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer($"[Attempted deferred despawn while un-spawned]"); + } + return; } - if (!IsSpawned) + if (!NetworkManagerOwner.DistributedAuthorityMode) { - NetworkLog.LogError($"Cannot defer despawning {name} because it is not spawned!"); + NetworkLog.LogError($"This method is only available in distributed authority mode."); return; } if (!HasAuthority) { - NetworkLog.LogError($"Only the authority can invoke {nameof(DeferDespawn)} and local Client-{NetworkManager.LocalClientId} is not the authority of {name}!"); + NetworkLog.LogError($"Only the authority can invoke {nameof(DeferDespawn)} and local Client-{NetworkManagerOwner.LocalClientId} is not the authority of {name}!"); return; } // Apply the relative tick offset for when this NetworkObject should be despawned on // non-authoritative instances. - DeferredDespawnTick = NetworkManager.ServerTime.Tick + tickOffset; + DeferredDespawnTick = NetworkManagerOwner.ServerTime.Tick + tickOffset; - var connectionManager = NetworkManager.ConnectionManager; + var connectionManager = NetworkManagerOwner.ConnectionManager; for (int i = 0; i < ChildNetworkBehaviours.Count; i++) { @@ -432,7 +437,7 @@ public void DeferDespawn(int tickOffset, bool destroy = true) } // DAHost handles sending updates to all clients - if (NetworkManager.DAHost) + if (NetworkManagerOwner.DAHost) { for (int i = 0; i < connectionManager.ConnectedClientsList.Count; i++) { @@ -601,17 +606,27 @@ internal void RemoveOwnershipExtended(OwnershipStatusExtended extended) /// true or false depending upon lock operation's success public bool SetOwnershipLock(bool lockOwnership = true) { - // If we are not in distributed autority mode, then exit early - if (!NetworkManager.DistributedAuthorityMode) + if (!IsSpawned) { - Debug.LogError($"[Feature Not Allowed In Client-Server Mode] Ownership flags are a distributed authority feature only!"); + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer("[Attempted Lock While un-spawned]"); + } + return false; } // If we don't have authority exit early if (!HasAuthority) { - NetworkLog.LogWarningServer($"[Attempted Lock Without Authority] Client-{NetworkManager.LocalClientId} is trying to lock ownership but does not have authority!"); + NetworkLog.LogWarningServer($"[Attempted Lock Without Authority] Client-{NetworkManagerOwner.LocalClientId} is trying to lock ownership but does not have authority!"); + return false; + } + + // If we are not in distributed autority mode, then exit early + if (!NetworkManagerOwner.DistributedAuthorityMode) + { + Debug.LogError($"[Feature Not Allowed In Client-Server Mode] Ownership flags are a distributed authority feature only!"); return false; } @@ -754,8 +769,18 @@ public enum OwnershipRequestStatus /// public OwnershipRequestStatus RequestOwnership() { + // An ownership change request can only be made if spawned. + if (!IsSpawned) + { + if (NetworkManagerOwner.LogLevel <= LogLevel.Normal) + { + NetworkLog.LogErrorServer("[Attempted ownership request while un-spawned]"); + } + + return OwnershipRequestStatus.Locked; + } // Exit early the local client is already the owner - if (OwnerClientId == NetworkManager.LocalClientId) + if (OwnerClientId == NetworkManagerOwner.LocalClientId) { return OwnershipRequestStatus.AlreadyOwner; } @@ -791,14 +816,14 @@ public OwnershipRequestStatus RequestOwnership() NetworkObjectId = NetworkObjectId, OwnerClientId = OwnerClientId, ClientIdCount = 1, - RequestClientId = NetworkManager.LocalClientId, + RequestClientId = NetworkManagerOwner.LocalClientId, ClientIds = new ulong[1] { OwnerClientId }, DistributedAuthorityMode = true, OwnershipFlags = (ushort)Ownership, }; - var sendTarget = NetworkManager.DAHost ? OwnerClientId : NetworkManager.ServerClientId; - NetworkManager.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, sendTarget); + var sendTarget = NetworkManagerOwner.DAHost ? OwnerClientId : NetworkManager.ServerClientId; + NetworkManagerOwner.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, sendTarget); return OwnershipRequestStatus.RequestSent; } @@ -863,7 +888,7 @@ internal void OwnershipRequest(ulong clientRequestingOwnership) // This action is always authorized as long as the client still has authority. // We need to pass in that this is a request approval ownership change. - NetworkManager.SpawnManager.ChangeOwnership(this, clientRequestingOwnership, HasAuthority, true); + NetworkManagerOwner.SpawnManager.ChangeOwnership(this, clientRequestingOwnership, HasAuthority, true); } else { @@ -877,15 +902,15 @@ internal void OwnershipRequest(ulong clientRequestingOwnership) { ChangeMessageType = ChangeOwnershipMessage.ChangeType.RequestDenied, NetworkObjectId = NetworkObjectId, - OwnerClientId = NetworkManager.LocalClientId, // Always use the local clientId (see above notes) + OwnerClientId = NetworkManagerOwner.LocalClientId, // Always use the local clientId (see above notes) RequestClientId = clientRequestingOwnership, DistributedAuthorityMode = true, OwnershipRequestResponseStatus = (byte)response, OwnershipFlags = (ushort)Ownership, }; - var sendTarget = NetworkManager.DAHost ? clientRequestingOwnership : NetworkManager.ServerClientId; - NetworkManager.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, sendTarget); + var sendTarget = NetworkManagerOwner.DAHost ? clientRequestingOwnership : NetworkManager.ServerClientId; + NetworkManagerOwner.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, sendTarget); } } @@ -982,7 +1007,7 @@ public enum OwnershipLockActions /// public bool SetOwnershipStatus(OwnershipStatus status, bool clearAndSet = false, OwnershipLockActions lockAction = OwnershipLockActions.None) { - if (status.HasFlag(OwnershipStatus.SessionOwner) && !NetworkManager.LocalClient.IsSessionOwner) + if (status.HasFlag(OwnershipStatus.SessionOwner) && !NetworkManagerOwner.LocalClient.IsSessionOwner) { NetworkLog.LogWarning("Only the session owner is allowed to set the ownership status to session owner only."); return false; @@ -1072,22 +1097,22 @@ internal void SendOwnershipStatusUpdate() OwnershipFlags = (ushort)Ownership, }; - if (NetworkManager.DAHost) + if (NetworkManagerOwner.DAHost) { foreach (var clientId in Observers) { - if (clientId == NetworkManager.LocalClientId) + if (clientId == NetworkManagerOwner.LocalClientId) { continue; } - NetworkManager.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, clientId); + NetworkManagerOwner.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, clientId); } } else { changeOwnership.ClientIdCount = Observers.Count; changeOwnership.ClientIds = Observers.ToArray(); - NetworkManager.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); + NetworkManagerOwner.ConnectionManager.SendMessage(ref changeOwnership, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); } } @@ -1114,14 +1139,21 @@ public bool HasOwnershipStatus(OwnershipStatus status) [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool InternalHasAuthority() { - var networkManager = NetworkManager; - return networkManager.DistributedAuthorityMode ? OwnerClientId == networkManager.LocalClientId : networkManager.IsServer; + if (!IsSpawned) + { + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer("[Attempted authority check while un-spawned]"); + } + return false; + } + return NetworkManagerOwner.DistributedAuthorityMode ? OwnerClientId == NetworkManagerOwner.LocalClientId : NetworkManagerOwner.IsServer; } /// /// The NetworkManager that owns this NetworkObject. /// This property controls where this NetworkObject belongs. - /// This property is null by default currently, which means that the above NetworkManager getter will return the Singleton. + /// This property will be null when the NetworkObject is not spawned. /// In the future this is the path where alternative NetworkManagers should be injected for running multi NetworkManagers /// internal NetworkManager NetworkManagerOwner; @@ -1166,17 +1198,17 @@ private bool InternalHasAuthority() /// /// Gets if the object is the personal clients player object /// - public bool IsLocalPlayer => NetworkManager != null && IsPlayerObject && OwnerClientId == NetworkManager.LocalClientId; + public bool IsLocalPlayer => IsSpawned && IsPlayerObject && OwnerClientId == NetworkManagerOwner.LocalClientId; /// /// Gets if the object is owned by the local player or if the object is the local player object /// - public bool IsOwner => NetworkManager != null && OwnerClientId == NetworkManager.LocalClientId; + public bool IsOwner => IsSpawned && OwnerClientId == NetworkManagerOwner.LocalClientId; /// - /// Gets Whether or not the object is owned by anyone + /// Gets whether or not the object is owned by anyone /// - public bool IsOwnedByServer => NetworkManager != null && OwnerClientId == NetworkManager.ServerClientId; + public bool IsOwnedByServer => OwnerClientId == NetworkManager.ServerClientId; /// /// Gets if the object has yet been spawned across the network @@ -1437,7 +1469,7 @@ public void NetworkShow(ulong clientId) if (!HasAuthority) { - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { throw new NotServerException($"Only the owner-authority can change visibility when distributed authority mode is enabled!"); } @@ -1449,7 +1481,7 @@ public void NetworkShow(ulong clientId) if (Observers.Contains(clientId)) { - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { Debug.LogError($"The object {name} is already visible to Client-{clientId}!"); return; @@ -1462,13 +1494,13 @@ public void NetworkShow(ulong clientId) if (CheckObjectVisibility != null && !CheckObjectVisibility(clientId)) { - if (NetworkManager.LogLevel <= LogLevel.Normal) + if (NetworkManagerOwner.LogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"[NetworkShow] Trying to make {nameof(NetworkObject)} {gameObject.name} visible to client ({clientId}) but {nameof(CheckObjectVisibility)} returned false!"); } return; } - NetworkManager.SpawnManager.MarkObjectForShowingTo(this, clientId); + NetworkManagerOwner.SpawnManager.MarkObjectForShowingTo(this, clientId); Observers.Add(clientId); } @@ -1500,7 +1532,13 @@ public static void NetworkShow(List networkObjects, ulong clientI for (int i = 0; i < networkObjects.Count; i++) { var networkObject = networkObjects[i]; - var networkManager = networkObject.NetworkManager; + var networkManager = networkObject.NetworkManagerOwner; + + if (!networkObject.IsSpawned) + { + // CHECK replace this by NetworkLog.LogWarning($"Trying to show object but is not spawned!"); continue; (change all in another PR) + throw new SpawnStateException("Object is not spawned"); + } if (networkManager.DistributedAuthorityMode && clientId == networkObject.OwnerClientId) { @@ -1514,9 +1552,9 @@ public static void NetworkShow(List networkObjects, ulong clientI // Distributed authority mode adjustments to log a network error and continue when trying to show a NetworkObject // that the local instance does not own - if (!networkObjects[i].HasAuthority) + if (!networkObject.HasAuthority) { - if (networkObjects[i].NetworkManager.DistributedAuthorityMode) + if (networkManager.DistributedAuthorityMode) { // It will log locally and to the "master-host". NetworkLog.LogErrorServer("Only the owner-authority can change visibility when distributed authority mode is enabled!"); @@ -1528,19 +1566,15 @@ public static void NetworkShow(List networkObjects, ulong clientI } } - if (!networkObjects[i].IsSpawned) - { - throw new SpawnStateException("Object is not spawned"); - } - if (networkObjects[i].Observers.Contains(clientId)) + if (networkObject.Observers.Contains(clientId)) { - throw new VisibilityChangeException($"{nameof(NetworkObject)} with NetworkId: {networkObjects[i].NetworkObjectId} is already visible"); + throw new VisibilityChangeException($"{nameof(NetworkObject)} with NetworkId: {networkObject.NetworkObjectId} is already visible"); } - if (networkObjects[i].NetworkManager != networkManager) + if (networkObject.NetworkManagerOwner != networkManager) { - throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(NetworkManager)); + throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(networkManager)); } } @@ -1571,9 +1605,9 @@ public void NetworkHide(ulong clientId) throw new SpawnStateException("Object is not spawned"); } - if (!HasAuthority && !NetworkManager.DAHost) + if (!HasAuthority && !NetworkManagerOwner.DAHost) { - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { throw new NotServerException($"Only the owner-authority can change visibility when distributed authority mode is enabled!"); } @@ -1583,11 +1617,11 @@ public void NetworkHide(ulong clientId) } } - if (!NetworkManager.SpawnManager.RemoveObjectFromShowingTo(this, clientId)) + if (!NetworkManagerOwner.SpawnManager.RemoveObjectFromShowingTo(this, clientId)) { if (!Observers.Contains(clientId)) { - if (NetworkManager.LogLevel <= LogLevel.Developer) + if (NetworkManagerOwner.LogLevel <= LogLevel.Developer) { Debug.LogWarning($"{name} is already hidden from Client-{clientId}! (ignoring)"); return; @@ -1599,41 +1633,41 @@ public void NetworkHide(ulong clientId) { NetworkObjectId = NetworkObjectId, DestroyGameObject = !IsSceneObject.Value, - IsDistributedAuthority = NetworkManager.DistributedAuthorityMode, - IsTargetedDestroy = NetworkManager.DistributedAuthorityMode, + IsDistributedAuthority = NetworkManagerOwner.DistributedAuthorityMode, + IsTargetedDestroy = NetworkManagerOwner.DistributedAuthorityMode, TargetClientId = clientId, // Just always populate this value whether we write it or not DeferredDespawnTick = DeferredDespawnTick, }; var size = 0; - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { - if (!NetworkManager.DAHost) + if (!NetworkManagerOwner.DAHost) { // Send destroy call to service or DAHost - size = NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); + size = NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); } else // DAHost mocking service { // Send destroy call - size = NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); + size = NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); // Broadcast the destroy to all clients so they can update their observers list - foreach (var client in NetworkManager.ConnectionManager.ConnectedClientIds) + foreach (var client in NetworkManagerOwner.ConnectionManager.ConnectedClientIds) { - if (client == clientId || client == NetworkManager.LocalClientId) + if (client == clientId || client == NetworkManagerOwner.LocalClientId) { continue; } - size += NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, client); + size += NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, client); } } } else { // Send destroy call - size = NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); + size = NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); } - NetworkManager.NetworkMetrics.TrackObjectDestroySent(clientId, this, size); + NetworkManagerOwner.NetworkMetrics.TrackObjectDestroySent(clientId, this, size); } } @@ -1664,7 +1698,7 @@ public static void NetworkHide(List networkObjects, ulong clientI for (int i = 0; i < networkObjects.Count; i++) { var networkObject = networkObjects[i]; - var networkManager = networkObject.NetworkManager; + var networkManager = networkObject.NetworkManagerOwner; if (networkManager.DistributedAuthorityMode && clientId == networkObject.OwnerClientId) { @@ -1678,9 +1712,9 @@ public static void NetworkHide(List networkObjects, ulong clientI // Distributed authority mode adjustments to log a network error and continue when trying to show a NetworkObject // that the local instance does not own - if (!networkObjects[i].HasAuthority) + if (!networkObject.HasAuthority) { - if (networkObjects[i].NetworkManager.DistributedAuthorityMode) + if (networkObject.NetworkManagerOwner.DistributedAuthorityMode) { // It will log locally and to the "master-host". NetworkLog.LogErrorServer($"Only the owner-authority can change hide a {nameof(NetworkObject)} when distributed authority mode is enabled!"); @@ -1692,20 +1726,21 @@ public static void NetworkHide(List networkObjects, ulong clientI } } + // CHECK, should I address this comment and replace all exceptions with log warnings/errors? (yes, in another PR, same as the comment below) // CLIENT SPAWNING TODO: Log error and continue as opposed to throwing an exception - if (!networkObjects[i].IsSpawned) + if (!networkObject.IsSpawned) { throw new SpawnStateException("Object is not spawned"); } - if (!networkObjects[i].Observers.Contains(clientId)) + if (!networkObject.Observers.Contains(clientId)) { - throw new VisibilityChangeException($"{nameof(NetworkObject)} with {nameof(NetworkObjectId)}: {networkObjects[i].NetworkObjectId} is already hidden"); + throw new VisibilityChangeException($"{nameof(NetworkObject)} with {nameof(NetworkObjectId)}: {networkObject.NetworkObjectId} is already hidden"); } - if (networkObjects[i].NetworkManager != networkManager) + if (networkObject.NetworkManagerOwner != networkManager) { - throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(NetworkManager)); + throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(networkManager)); } } @@ -1717,34 +1752,35 @@ public static void NetworkHide(List networkObjects, ulong clientI private void OnDestroy() { + var networkManager = NetworkManager; // If no NetworkManager is assigned, then just exit early - if (!NetworkManager) + if (!networkManager) { return; } // An authorized destroy is when done by the authority instance or done due to a scene event and the NetworkObject // was marked as destroy pending scene event (which means the destroy with scene property was set). - var isAuthorityDestroy = HasAuthority || NetworkManager.DAHost || DestroyPendingSceneEvent; + var isAuthorityDestroy = HasAuthority || networkManager.DAHost || DestroyPendingSceneEvent; - if (NetworkManager.IsListening && !isAuthorityDestroy && IsSpawned && - (IsSceneObject == null || (IsSceneObject.Value != true))) + if (IsSpawned && !isAuthorityDestroy && networkManager.IsListening && + (IsSceneObject == null || IsSceneObject.Value != true)) { // If we destroyed a GameObject with a NetworkObject component on the non-authority side, handle cleaning up the SceneMigrationSynchronization. - NetworkManager.SpawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); + networkManager.SpawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); // Clients should not despawn NetworkObjects while connected to a session, but we don't want to destroy the current call stack // if this happens. Instead, we should just generate a network log error and exit early (as long as we are not shutting down). - if (!NetworkManager.ShutdownInProgress) + if (!networkManager.ShutdownInProgress) { // Since we still have a session connection, log locally and on the server to inform user of this issue. // If the NetworkObject's GameObject is not valid or the scene is no longer valid or loaded, then this was due to the // unloading of a scene which is done by the authority... if (gameObject != null && gameObject.scene.IsValid() && gameObject.scene.isLoaded) { - if (NetworkManager.LogLevel <= LogLevel.Error) + if (networkManager.LogLevel <= LogLevel.Error) { - if (NetworkManager.DistributedAuthorityMode) + if (networkManager.DistributedAuthorityMode) { NetworkLog.LogError($"[Invalid Destroy][{gameObject.name}][NetworkObjectId:{NetworkObjectId}] Destroy a spawned {nameof(NetworkObject)} on a non-owner client is not valid during a distributed authority session. Call {nameof(Destroy)} or {nameof(Despawn)} on the client-owner instead."); } @@ -1765,13 +1801,13 @@ private void OnDestroy() } // Always attempt to remove from scene changed updates - NetworkManager.SpawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); + networkManager.SpawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); - if (NetworkManager.SpawnManager != null && NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) + if (networkManager.SpawnManager != null && networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) { if (this == networkObject) { - NetworkManager.SpawnManager.OnDespawnObject(networkObject, false); + networkManager.SpawnManager.OnDespawnObject(networkObject, false); } } } @@ -1783,16 +1819,17 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla { NetworkManagerOwner = NetworkManager.Singleton; } - if (!NetworkManager.IsListening) + + if (!NetworkManagerOwner.IsListening) { - throw new NotListeningException($"{nameof(NetworkManager)} is not listening, start a server or host before spawning objects"); + throw new NotListeningException($"{nameof(NetworkManagerOwner)} is not listening, start a server or host before spawning objects"); } - if ((!NetworkManager.IsServer && !NetworkManager.DistributedAuthorityMode) || (NetworkManager.DistributedAuthorityMode && !NetworkManager.LocalClient.IsSessionOwner && NetworkManager.LocalClientId != ownerClientId)) + if ((!NetworkManagerOwner.IsServer && !NetworkManagerOwner.DistributedAuthorityMode) || (NetworkManagerOwner.DistributedAuthorityMode && !NetworkManagerOwner.LocalClient.IsSessionOwner && NetworkManagerOwner.LocalClientId != ownerClientId)) { - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { - throw new NotServerException($"When distributed authority mode is enabled, you can only spawn NetworkObjects that belong to the local instance! Local instance id {NetworkManager.LocalClientId} is not the same as the assigned owner id: {ownerClientId}!"); + throw new NotServerException($"When distributed authority mode is enabled, you can only spawn NetworkObjects that belong to the local instance! Local instance id {NetworkManagerOwner.LocalClientId} is not the same as the assigned owner id: {ownerClientId}!"); } else { @@ -1800,19 +1837,19 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla } } - if (NetworkManager.DistributedAuthorityMode) + if (NetworkManagerOwner.DistributedAuthorityMode) { - if (NetworkManager.LocalClient == null || !NetworkManager.IsConnectedClient || !NetworkManager.ConnectionManager.LocalClient.IsApproved) + if (NetworkManagerOwner.LocalClient == null || !NetworkManagerOwner.IsConnectedClient || !NetworkManagerOwner.ConnectionManager.LocalClient.IsApproved) { Debug.LogError($"Cannot spawn {name} until the client is fully connected to the session!"); return; } - if (NetworkManager.NetworkConfig.EnableSceneManagement) + if (NetworkManagerOwner.NetworkConfig.EnableSceneManagement) { - if (!NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(gameObject.scene.handle)) + if (!NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(gameObject.scene.handle)) { // Most likely this issue is due to an integration test - if (NetworkManager.LogLevel <= LogLevel.Developer) + if (NetworkManagerOwner.LogLevel <= LogLevel.Developer) { NetworkLog.LogWarning($"Failed to find scene handle {gameObject.scene.handle} for {gameObject.name}!"); } @@ -1821,43 +1858,43 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla } else { - NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[gameObject.scene.handle]; + NetworkSceneHandle = NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle[gameObject.scene.handle]; } } if (DontDestroyWithOwner && !IsOwnershipDistributable) { //Ownership |= OwnershipStatus.Distributable; // DANGO-TODO: Review over don't destroy with owner being set but DistributeOwnership not being set - if (NetworkManager.LogLevel == LogLevel.Developer) + if (NetworkManagerOwner.LogLevel == LogLevel.Developer) { NetworkLog.LogWarning("DANGO-TODO: Review over don't destroy with owner being set but DistributeOwnership not being set. For now, if the NetworkObject does not destroy with the owner it will set ownership to SessionOwner."); } } } - NetworkManager.SpawnManager.AuthorityLocalSpawn(this, NetworkManager.SpawnManager.GetNetworkObjectId(), IsSceneObject.HasValue && IsSceneObject.Value, playerObject, ownerClientId, destroyWithScene); + NetworkManagerOwner.SpawnManager.AuthorityLocalSpawn(this, NetworkManagerOwner.SpawnManager.GetNetworkObjectId(), IsSceneObject.HasValue && IsSceneObject.Value, playerObject, ownerClientId, destroyWithScene); - if ((NetworkManager.DistributedAuthorityMode && NetworkManager.DAHost) || (!NetworkManager.DistributedAuthorityMode && NetworkManager.IsServer)) + if ((NetworkManagerOwner.DistributedAuthorityMode && NetworkManagerOwner.DAHost) || (!NetworkManagerOwner.DistributedAuthorityMode && NetworkManagerOwner.IsServer)) { - for (int i = 0; i < NetworkManager.ConnectedClientsList.Count; i++) + for (int i = 0; i < NetworkManagerOwner.ConnectedClientsList.Count; i++) { - if (NetworkManager.ConnectedClientsList[i].ClientId == NetworkManager.ServerClientId) + if (NetworkManagerOwner.ConnectedClientsList[i].ClientId == NetworkManager.ServerClientId) { continue; } - if (Observers.Contains(NetworkManager.ConnectedClientsList[i].ClientId)) + if (Observers.Contains(NetworkManagerOwner.ConnectedClientsList[i].ClientId)) { - NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ConnectedClientsList[i].ClientId, this); + NetworkManagerOwner.SpawnManager.SendSpawnCallForObject(NetworkManagerOwner.ConnectedClientsList[i].ClientId, this); } } } - else if (NetworkManager.DistributedAuthorityMode && !NetworkManager.DAHost) + else if (NetworkManagerOwner.DistributedAuthorityMode && !NetworkManagerOwner.DAHost) { // If spawning with observers or if not spawning with observers but the observer count is greater than 1 (i.e. owner/authority creating), // then we want to send a spawn notification. if (SpawnWithObservers || !SpawnWithObservers && Observers.Count > 1) { - NetworkManager.SpawnManager.SendSpawnCallForObject(NetworkManager.ServerClientId, this); + NetworkManagerOwner.SpawnManager.SendSpawnCallForObject(NetworkManager.ServerClientId, this); } } else @@ -1946,7 +1983,8 @@ public NetworkObject InstantiateAndSpawn(NetworkManager networkManager, ulong ow /// Should the object be destroyed when the scene is changed public void Spawn(bool destroyWithScene = false) { - var clientId = NetworkManager.DistributedAuthorityMode ? NetworkManager.LocalClientId : NetworkManager.ServerClientId; + var networkManager = NetworkManager; + var clientId = networkManager.DistributedAuthorityMode ? networkManager.LocalClientId : NetworkManager.ServerClientId; SpawnInternal(destroyWithScene, clientId, false); } @@ -1984,7 +2022,11 @@ public void Despawn(bool destroy = true) { if (!IsSpawned) { - NetworkLog.LogErrorServer("Object is not spawned!"); + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer($"[Attempted despawn while un-spawned]"); + } + return; } @@ -1992,7 +2034,7 @@ public void Despawn(bool destroy = true) { behavior.MarkVariablesDirty(false); } - NetworkManager.SpawnManager.DespawnObject(this, destroy); + NetworkManagerOwner.SpawnManager.DespawnObject(this, destroy); } internal void ResetOnDespawn() @@ -2010,7 +2052,15 @@ internal void ResetOnDespawn() /// public void RemoveOwnership() { - NetworkManager.SpawnManager.RemoveOwnership(this); + if (!IsSpawned) + { + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer("[Attempted ownership removal while un-spawned]"); + } + return; + } + NetworkManagerOwner.SpawnManager.RemoveOwnership(this); } /// @@ -2019,7 +2069,17 @@ public void RemoveOwnership() /// The new owner clientId public void ChangeOwnership(ulong newOwnerClientId) { - NetworkManager.SpawnManager.ChangeOwnership(this, newOwnerClientId, HasAuthority); + if (!IsSpawned) + { + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer("[Attempted ownership change while un-spawned]"); + } + + return; + } + + NetworkManagerOwner.SpawnManager.ChangeOwnership(this, newOwnerClientId, HasAuthority); } /// @@ -2028,14 +2088,24 @@ public void ChangeOwnership(ulong newOwnerClientId) /// internal void InvokeBehaviourOnOwnershipChanged(ulong originalOwnerClientId, ulong newOwnerClientId) { - var distributedAuthorityMode = NetworkManager.DistributedAuthorityMode; - var isServer = NetworkManager.IsServer; - var isPreviousOwner = originalOwnerClientId == NetworkManager.LocalClientId; - var isNewOwner = newOwnerClientId == NetworkManager.LocalClientId; + if (!IsSpawned) + { + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer($"[Attempted behavior invoke on ownership changed while un-spawned]"); + } + + return; + } + + var distributedAuthorityMode = NetworkManagerOwner.DistributedAuthorityMode; + var isServer = NetworkManagerOwner.IsServer; + var isPreviousOwner = originalOwnerClientId == NetworkManagerOwner.LocalClientId; + var isNewOwner = newOwnerClientId == NetworkManagerOwner.LocalClientId; if (distributedAuthorityMode || isPreviousOwner) { - NetworkManager.SpawnManager.UpdateOwnershipTable(this, originalOwnerClientId, true); + NetworkManagerOwner.SpawnManager.UpdateOwnershipTable(this, originalOwnerClientId, true); } foreach (var childBehaviour in ChildNetworkBehaviours) @@ -2047,7 +2117,7 @@ internal void InvokeBehaviourOnOwnershipChanged(ulong originalOwnerClientId, ulo } } - NetworkManager.SpawnManager.UpdateOwnershipTable(this, newOwnerClientId); + NetworkManagerOwner.SpawnManager.UpdateOwnershipTable(this, newOwnerClientId); if (distributedAuthorityMode || isServer || isNewOwner) { @@ -2160,7 +2230,7 @@ internal void SetNetworkParenting(ulong? latestParent, bool worldPositionStays) /// /// The new parent for this NetworkObject transform will be the child of. /// If true, the parent-relative position, scale and rotation are modified such that the object keeps the same world space position, rotation and scale as before. - /// Whether or not reparenting was successful. + /// Whether or not re-parenting was successful. public bool TrySetParent(Transform parent, bool worldPositionStays = true) { // If we are removing ourself from a parent @@ -2180,7 +2250,7 @@ public bool TrySetParent(Transform parent, bool worldPositionStays = true) /// /// The new parent for this NetworkObject transform will be the child of. /// If true, the parent-relative position, scale and rotation are modified such that the object keeps the same world space position, rotation and scale as before. - /// Whether or not reparenting was successful. + /// Whether or not re-parenting was successful. public bool TrySetParent(GameObject parent, bool worldPositionStays = true) { // If we are removing ourself from a parent @@ -2224,12 +2294,7 @@ public bool TryRemoveParent(bool worldPositionStays = true) /// Whether or not reparenting was successful. public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true) { - if (!AutoObjectParentSync) - { - return false; - } - - if (NetworkManager == null || !NetworkManager.IsListening) + if (!AutoObjectParentSync || !IsSpawned || !NetworkManagerOwner.IsListening) { return false; } @@ -2240,7 +2305,7 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true) // If we don't have authority and we are not shutting down, then don't allow any parenting. // If we are shutting down and don't have authority then allow it. - if (!isAuthority && !NetworkManager.ShutdownInProgress) + if (!isAuthority && !NetworkManagerOwner.ShutdownInProgress) { return false; } @@ -2250,7 +2315,7 @@ public bool TrySetParent(NetworkObject parent, bool worldPositionStays = true) internal bool InternalTrySetParent(NetworkObject parent, bool worldPositionStays = true) { - if (parent != null && (IsSpawned ^ parent.IsSpawned) && NetworkManager != null && !NetworkManager.ShutdownInProgress) + if (parent && (IsSpawned ^ parent.IsSpawned) && !NetworkManager.ShutdownInProgress) { if (NetworkManager.LogLevel <= LogLevel.Developer) { @@ -2278,7 +2343,7 @@ internal bool InternalTrySetParent(NetworkObject parent, bool worldPositionStays private void OnTransformParentChanged() { - if (!AutoObjectParentSync || NetworkManager.ShutdownInProgress) + if (!AutoObjectParentSync) { return; } @@ -2288,8 +2353,13 @@ private void OnTransformParentChanged() return; } - if (NetworkManager == null || !NetworkManager.IsListening) + var networkManager = NetworkManager; + if (!IsSpawned || !networkManager.IsListening) { + if (networkManager.ShutdownInProgress) + { + return; + } // DANGO-TODO: Review as to whether we want to provide a better way to handle changing parenting of objects when the // object is not spawned. Really, we shouldn't care about these types of changes. if (NetworkManager.DistributedAuthorityMode && m_CachedParent != null && transform.parent == null) @@ -2298,20 +2368,19 @@ private void OnTransformParentChanged() return; } transform.parent = m_CachedParent; - Debug.LogException(new NotListeningException($"{nameof(NetworkManager)} is not listening, start a server or host before reparenting")); + Debug.LogException(new NotListeningException($"{nameof(networkManager)} is not listening, start a server or host before reparenting")); return; } var isAuthority = false; // With distributed authority, we need to track "valid authoritative" parenting changes. // So, either the authority or AuthorityAppliedParenting is considered a "valid parenting change". isAuthority = HasAuthority || AuthorityAppliedParenting || (AllowOwnerToParent && IsOwner); - var distributedAuthority = NetworkManager.DistributedAuthorityMode; + var distributedAuthority = NetworkManagerOwner.DistributedAuthorityMode; - // If we do not have authority and we are spawned - if (!isAuthority && IsSpawned) + // If we do not have authority + if (!isAuthority) { - - // If the cached parent has not already been set and we are in distributed authority mode, then log an exception and exit early as a non-authority instance + // If the cached parent has not already been set, and we are in distributed authority mode, then log an exception and exit early as a non-authority instance // is trying to set the parent. if (distributedAuthority) { @@ -2345,10 +2414,9 @@ private void OnTransformParentChanged() } var removeParent = false; var parentTransform = transform.parent; - var parentObject = (NetworkObject)null; if (parentTransform != null) { - if (!transform.parent.TryGetComponent(out parentObject)) + if (!parentTransform.TryGetComponent(out NetworkObject parentObject)) { transform.parent = m_CachedParent; AuthorityAppliedParenting = false; @@ -2397,7 +2465,7 @@ private void OnTransformParentChanged() } // If we're not the server, we should tell the server about this parent change - if (!NetworkManager.IsServer) + if (!NetworkManagerOwner.IsServer) { // Don't send a message in DA mode if we're the only observers of this object (we're the only authority). if (distributedAuthority && Observers.Count <= 1) @@ -2405,12 +2473,12 @@ private void OnTransformParentChanged() return; } - NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); + NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, NetworkManager.ServerClientId); return; } // Otherwise we are a Server (client-server or DAHost). Send to all observers - foreach (var clientId in NetworkManager.ConnectionManager.ConnectedClientIds) + foreach (var clientId in NetworkManagerOwner.ConnectionManager.ConnectedClientIds) { if (clientId == NetworkManager.ServerClientId) { @@ -2418,7 +2486,7 @@ private void OnTransformParentChanged() } if (Observers.Contains(clientId)) { - NetworkManager.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); + NetworkManagerOwner.ConnectionManager.SendMessage(ref message, MessageDeliveryType.DefaultDelivery, clientId); } } } @@ -2513,16 +2581,17 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa return true; } + var networkManager = NetworkManager; // If we have a latest parent id but it hasn't been spawned yet, then add this instance to the orphanChildren // HashSet and return false (i.e. parenting not applied yet) - if (m_LatestParent.HasValue && !NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(m_LatestParent.Value)) + if (m_LatestParent.HasValue && !networkManager.SpawnManager.SpawnedObjects.ContainsKey(m_LatestParent.Value)) { OrphanChildren.Add(this); return false; } // If we made it here, then parent this instance under the parentObject - var parentObject = NetworkManager.SpawnManager.SpawnedObjects[m_LatestParent.Value]; + var parentObject = networkManager.SpawnManager.SpawnedObjects[m_LatestParent.Value]; // If we are handling an orphaned child and its parent is orphaned too, then don't parent yet. if (orphanedChildPass) @@ -2568,7 +2637,7 @@ internal void InvokeBehaviourNetworkPreSpawn() internal void InvokeBehaviourNetworkSpawn() { - NetworkManager.SpawnManager.UpdateOwnershipTable(this, OwnerClientId); + NetworkManagerOwner.SpawnManager.UpdateOwnershipTable(this, OwnerClientId); // Always invoke all InternalOnNetworkSpawn methods on each child NetworkBehaviour // ** before ** invoking OnNetworkSpawn. @@ -2633,14 +2702,23 @@ internal void InternalInSceneNetworkObjectsSpawned() internal void InvokeBehaviourNetworkDespawn() { + if (!IsSpawned) + { + if (NetworkManager.LogLevel == LogLevel.Error) + { + NetworkLog.LogErrorServer("[Attempted network despawn behavior invoke while un-spawned]"); + } + + return; + } // Invoke OnNetworkPreDespawn on all child behaviours for (int i = 0; i < ChildNetworkBehaviours.Count; i++) { ChildNetworkBehaviours[i].InternalOnNetworkPreDespawn(); } - NetworkManager.SpawnManager.UpdateOwnershipTable(this, OwnerClientId, true); - NetworkManager.SpawnManager.RemoveNetworkObjectFromSceneChangedUpdates(this); + NetworkManagerOwner.SpawnManager.UpdateOwnershipTable(this, OwnerClientId, true); + NetworkManagerOwner.SpawnManager.RemoveNetworkObjectFromSceneChangedUpdates(this); for (int i = 0; i < ChildNetworkBehaviours.Count; i++) { @@ -2740,7 +2818,7 @@ internal void SynchronizeOwnerNetworkVariables(ulong originalOwnerId, ulong orig // Force send a state update for all owner read NetworkVariables and any currently dirty // owner write NetworkVariables. - NetworkManager.BehaviourUpdater.NetworkBehaviourUpdate(true); + NetworkManagerOwner.BehaviourUpdater.NetworkBehaviourUpdate(true); } // NGO currently guarantees that the client will receive spawn data for all objects in one network tick. @@ -2956,7 +3034,7 @@ public struct TransformData : INetworkSerializeByMemcpy public void Serialize(FastBufferWriter writer) { - if (OwnerObject.NetworkManager.DistributedAuthorityMode) + if (OwnerObject.NetworkManagerOwner.DistributedAuthorityMode) { HasOwnershipFlags = true; SpawnWithObservers = OwnerObject.SpawnWithObservers; @@ -3005,7 +3083,7 @@ public void Serialize(FastBufferWriter writer) // The NetworkSceneHandle is the server-side relative // scene handle that the NetworkObject resides in. - if (OwnerObject.NetworkManager.DistributedAuthorityMode) + if (OwnerObject.NetworkManagerOwner.DistributedAuthorityMode) { writer.WriteValue(OwnerObject.NetworkSceneHandle); } @@ -3181,7 +3259,7 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager IsSceneObject = IsSceneObject ?? true, DestroyWithScene = DestroyWithScene, DontDestroyWithOwner = DontDestroyWithOwner, - HasOwnershipFlags = NetworkManager.DistributedAuthorityMode, + HasOwnershipFlags = NetworkManagerOwner.DistributedAuthorityMode, OwnershipFlags = (ushort)Ownership, SyncObservers = syncObservers, Observers = syncObservers ? Observers.ToArray() : null, @@ -3195,7 +3273,7 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager // Handle Parenting if (!AlwaysReplicateAsRoot && obj.HasParent) { - var parentNetworkObject = transform.parent.GetComponent(); + var parentNetworkObject = m_CachedParent.GetComponent(); if (parentNetworkObject) { @@ -3418,9 +3496,9 @@ internal void SubscribeToActiveSceneForSynch() /// private void CurrentlyActiveSceneChanged(Scene current, Scene next) { - // Early exit if there is no NetworkManager assigned, the NetworkManager is shutting down, the NetworkObject - // is not spawned, or an in-scene placed NetworkObject - if (NetworkManager == null || NetworkManager.ShutdownInProgress || !IsSpawned || IsSceneObject != false) + // Early exit if the NetworkObject is not spawned, is an in-scene placed NetworkObject, + // or the NetworkManager is shutting down. + if (!IsSpawned || IsSceneObject != false || NetworkManagerOwner.ShutdownInProgress) { return; } @@ -3443,13 +3521,13 @@ private void CurrentlyActiveSceneChanged(Scene current, Scene next) /// internal void SceneChangedUpdate(Scene scene, bool notify = false) { - // Avoiding edge case scenarios, if no NetworkSceneManager exit early - if (NetworkManager.SceneManager == null || !IsSpawned) + // Avoiding edge case scenarios, if not spawned or no NetworkSceneManager exit early + if (!IsSpawned || NetworkManagerOwner.SceneManager == null) { return; } - if (NetworkManager.SceneManager.IsSceneEventInProgress()) + if (NetworkManagerOwner.SceneManager.IsSceneEventInProgress()) { return; } @@ -3458,17 +3536,17 @@ internal void SceneChangedUpdate(Scene scene, bool notify = false) SceneOriginHandle = scene.handle; // non-authority needs to update the NetworkSceneHandle - if (!isAuthority && NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(SceneOriginHandle)) + if (!isAuthority && NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(SceneOriginHandle)) { - NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[SceneOriginHandle]; + NetworkSceneHandle = NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle[SceneOriginHandle]; } else if (isAuthority) { // Since the authority is the source of truth for the NetworkSceneHandle, // the NetworkSceneHandle is the same as the SceneOriginHandle. - if (NetworkManager.DistributedAuthorityMode && NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(SceneOriginHandle)) + if (NetworkManagerOwner.DistributedAuthorityMode && NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle.ContainsKey(SceneOriginHandle)) { - NetworkSceneHandle = NetworkManager.SceneManager.ClientSceneHandleToServerSceneHandle[SceneOriginHandle]; + NetworkSceneHandle = NetworkManagerOwner.SceneManager.ClientSceneHandleToServerSceneHandle[SceneOriginHandle]; } else { @@ -3476,22 +3554,22 @@ internal void SceneChangedUpdate(Scene scene, bool notify = false) } } else // Otherwise, the client did not find the client to server scene handle - if (NetworkManager.LogLevel == LogLevel.Developer) + if (NetworkManagerOwner.LogLevel == LogLevel.Developer) { // There could be a scenario where a user has some client-local scene loaded that they migrate the NetworkObject // into, but that scenario seemed very edge case and under most instances a user should be notified that this // server - client scene handle mismatch has occurred. It also seemed pertinent to make the message replicate to // the server-side too. - NetworkLog.LogWarningServer($"[Client-{NetworkManager.LocalClientId}][{gameObject.name}] Server - " + + NetworkLog.LogWarningServer($"[Client-{NetworkManagerOwner.LocalClientId}][{gameObject.name}] Server - " + $"client scene mismatch detected! Client-side scene handle ({SceneOriginHandle}) for scene ({gameObject.scene.name})" + $"has no associated server side (network) scene handle!"); } OnMigratedToNewScene?.Invoke(); // Only the authority side will notify clients of non-parented NetworkObject scene changes - if (isAuthority && notify && transform.parent == null) + if (isAuthority && notify && !transform.parent) { - NetworkManager.SceneManager.NotifyNetworkObjectSceneChanged(this); + NetworkManagerOwner.SceneManager.NotifyNetworkObjectSceneChanged(this); } } @@ -3519,11 +3597,11 @@ private void Awake() /// internal bool UpdateForSceneChanges() { - // Early exit if SceneMigrationSynchronization is disabled, there is no NetworkManager assigned, + // Early exit if SceneMigrationSynchronization is disabled, // the NetworkManager is shutting down, the NetworkObject is not spawned, it is an in-scene placed // NetworkObject, or the GameObject's current scene handle is the same as the SceneOriginHandle - if (!SceneMigrationSynchronization || !IsSpawned || NetworkManager == null || NetworkManager.ShutdownInProgress || - !NetworkManager.NetworkConfig.EnableSceneManagement || IsSceneObject != false || !gameObject) + if (!SceneMigrationSynchronization || !IsSpawned || NetworkManagerOwner.ShutdownInProgress || + !NetworkManagerOwner.NetworkConfig.EnableSceneManagement || IsSceneObject != false || !gameObject) { // Stop checking for a scene migration return false; @@ -3547,17 +3625,18 @@ internal bool UpdateForSceneChanges() /// appropriate hash value internal uint CheckForGlobalObjectIdHashOverride() { - if (NetworkManager.IsServer || NetworkManager.DistributedAuthorityMode) + var networkManager = NetworkManager; + if (networkManager.IsServer || networkManager.DistributedAuthorityMode) { - if (NetworkManager.PrefabHandler.ContainsHandler(this)) + if (networkManager.PrefabHandler.ContainsHandler(this)) { - var globalObjectIdHash = NetworkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); + var globalObjectIdHash = networkManager.PrefabHandler.GetSourceGlobalObjectIdHash(GlobalObjectIdHash); return globalObjectIdHash == 0 ? GlobalObjectIdHash : globalObjectIdHash; } // If scene management is disabled and this is an in-scene placed NetworkObject then go ahead // and send the InScenePlacedSourcePrefab's GlobalObjectIdHash value (i.e. what to dynamically spawn) - if (!NetworkManager.NetworkConfig.EnableSceneManagement && IsSceneObject.Value && InScenePlacedSourceGlobalObjectIdHash != 0) + if (!networkManager.NetworkConfig.EnableSceneManagement && IsSceneObject.Value && InScenePlacedSourceGlobalObjectIdHash != 0) { return InScenePlacedSourceGlobalObjectIdHash; } @@ -3575,9 +3654,9 @@ internal uint CheckForGlobalObjectIdHashOverride() else { // For legacy manual instantiation and spawning, check the OverrideToNetworkPrefab for a possible match - if (NetworkManager.NetworkConfig.Prefabs.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash)) + if (networkManager.NetworkConfig.Prefabs.OverrideToNetworkPrefab.ContainsKey(GlobalObjectIdHash)) { - return NetworkManager.NetworkConfig.Prefabs.OverrideToNetworkPrefab[GlobalObjectIdHash]; + return networkManager.NetworkConfig.Prefabs.OverrideToNetworkPrefab[GlobalObjectIdHash]; } } } @@ -3594,7 +3673,7 @@ internal void OnNetworkBehaviourDestroyed(NetworkBehaviour networkBehaviour) { if (networkBehaviour.IsSpawned && IsSpawned) { - if (NetworkManager?.LogLevel == LogLevel.Developer) + if (NetworkManagerOwner?.LogLevel == LogLevel.Developer) { NetworkLog.LogWarning($"{nameof(NetworkBehaviour)}-{networkBehaviour.name} is being destroyed while {nameof(NetworkObject)}-{name} is still spawned! (could break state synchronization)"); }