diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs index ff70a08e99..d7b7e70afa 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs @@ -1508,7 +1508,7 @@ internal void OnClientDisconnectFromServer(ulong clientId) if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].PlayerObject.GlobalObjectIdHash)) { PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].PlayerObject); - SpawnManager.OnDespawnObject(ConnectedClients[clientId].PlayerObject.NetworkObjectId, false); + SpawnManager.OnDespawnObject(ConnectedClients[clientId].PlayerObject, false); } else { @@ -1526,7 +1526,7 @@ internal void OnClientDisconnectFromServer(ulong clientId) if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].OwnedObjects[i].GlobalObjectIdHash)) { PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].OwnedObjects[i]); - SpawnManager.OnDespawnObject(ConnectedClients[clientId].OwnedObjects[i].NetworkObjectId, false); + SpawnManager.OnDespawnObject(ConnectedClients[clientId].OwnedObjects[i], false); } else { diff --git a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs index 1194c87ae0..c166c978ac 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Core/NetworkObject.cs @@ -405,9 +405,9 @@ public static void NetworkHide(List networkObjects, ulong clientI private void OnDestroy() { - if (NetworkManager != null && NetworkManager.SpawnManager != null && NetworkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId)) + if (NetworkManager != null && NetworkManager.SpawnManager != null && NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) { - NetworkManager.SpawnManager.OnDespawnObject(NetworkObjectId, false); + NetworkManager.SpawnManager.OnDespawnObject(networkObject, false); } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Messaging/InternalMessageHandler.cs b/com.unity.multiplayer.mlapi/Runtime/Messaging/InternalMessageHandler.cs index 82a8be7f1e..b92a1f9ded 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Messaging/InternalMessageHandler.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Messaging/InternalMessageHandler.cs @@ -190,7 +190,15 @@ public void HandleDestroyObject(ulong clientId, Stream stream) using (var reader = PooledNetworkReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); - NetworkManager.SpawnManager.OnDespawnObject(networkId, true); + if (!NetworkManager.SpawnManager.SpawnedObjects.TryGetValue(networkId, out NetworkObject networkObject)) + { + // This is the same check and log message that happens inside OnDespawnObject, but we have to do it here + // while we still have access to the network ID, otherwise the log message will be less useful. + Debug.LogWarning($"Trying to destroy object {networkId} but it doesn't seem to exist anymore!"); + return; + } + + NetworkManager.SpawnManager.OnDespawnObject(networkObject, true); } } diff --git a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs index 593bdd521e..10b08966f0 100644 --- a/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.multiplayer.mlapi/Runtime/Spawning/NetworkSpawnManager.cs @@ -460,7 +460,7 @@ internal void DespawnObject(NetworkObject networkObject, bool destroyObject = fa throw new NotServerException("Only server can despawn objects"); } - OnDespawnObject(networkObject.NetworkObjectId, destroyObject); + OnDespawnObject(networkObject, destroyObject); } // Makes scene objects ready to be reused @@ -498,7 +498,7 @@ internal void ServerDestroySpawnedSceneObjects() if (NetworkManager.PrefabHandler != null && NetworkManager.PrefabHandler.ContainsHandler(sobj)) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(sobj); - OnDespawnObject(sobj.NetworkObjectId, false); + OnDespawnObject(sobj, false); } else { @@ -522,7 +522,7 @@ internal void DestroyNonSceneObjects() { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObjects[i]); - OnDespawnObject(networkObjects[i].NetworkObjectId, false); + OnDespawnObject(networkObjects[i], false); } else { @@ -546,7 +546,7 @@ internal void DestroySceneObjects() if (NetworkManager.PrefabHandler.ContainsHandler(networkObjects[i])) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObjects[i]); - OnDespawnObject(networkObjects[i].NetworkObjectId, false); + OnDespawnObject(networkObjects[i], false); } else { @@ -607,17 +607,24 @@ internal void ClientCollectSoftSyncSceneObjectSweep(NetworkObject[] networkObjec } } - internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) + internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObject) { if (NetworkManager == null) { return; } + // We have to do this check first as subsequent checks assume we can access NetworkObjectId. + if (networkObject == null) + { + Debug.LogWarning($"Trying to destroy network object but it is null"); + return; + } + // Removal of spawned object - if (!SpawnedObjects.TryGetValue(networkObjectId, out NetworkObject networkObject)) + if (!SpawnedObjects.ContainsKey(networkObject.NetworkObjectId)) { - Debug.LogWarning($"Trying to destroy object {networkObjectId} but it doesn't seem to exist anymore!"); + Debug.LogWarning($"Trying to destroy object {networkObject.NetworkObjectId} but it doesn't seem to exist anymore!"); return; } @@ -625,13 +632,13 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) foreach (var spawnedNetObj in SpawnedObjectsList) { var (isReparented, latestParent) = spawnedNetObj.GetNetworkParenting(); - if (isReparented && latestParent == networkObjectId) + if (isReparented && latestParent == networkObject.NetworkObjectId) { spawnedNetObj.gameObject.transform.parent = null; if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { - NetworkLog.LogWarning($"{nameof(NetworkObject)} #{spawnedNetObj.NetworkObjectId} moved to the root because its parent {nameof(NetworkObject)} #{networkObjectId} is destroyed"); + NetworkLog.LogWarning($"{nameof(NetworkObject)} #{spawnedNetObj.NetworkObjectId} moved to the root because its parent {nameof(NetworkObject)} #{networkObject.NetworkObjectId} is destroyed"); } } } @@ -641,7 +648,7 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) //Someone owns it. for (int i = networkClient.OwnedObjects.Count - 1; i > -1; i--) { - if (networkClient.OwnedObjects[i].NetworkObjectId == networkObjectId) + if (networkClient.OwnedObjects[i].NetworkObjectId == networkObject.NetworkObjectId) { networkClient.OwnedObjects.RemoveAt(i); } @@ -657,7 +664,7 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) { ReleasedNetworkObjectIds.Enqueue(new ReleasedNetworkId() { - NetworkId = networkObjectId, + NetworkId = networkObject.NetworkObjectId, ReleaseTime = Time.unscaledTime }); } @@ -673,13 +680,13 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) var buffer = PooledNetworkBuffer.Get(); using (var writer = PooledNetworkWriter.Get(buffer)) { - writer.WriteUInt64Packed(networkObjectId); + writer.WriteUInt64Packed(networkObject.NetworkObjectId); var queueItem = new RpcFrameQueueItem { UpdateStage = NetworkUpdateStage.PostLateUpdate, QueueItemType = RpcQueueContainer.QueueItemType.DestroyObject, - NetworkId = networkObjectId, + NetworkId = networkObject.NetworkObjectId, NetworkBuffer = buffer, NetworkChannel = NetworkChannel.Internal, ClientNetworkIds = NetworkManager.ConnectedClientsList.Select(c => c.ClientId).ToArray() @@ -699,7 +706,7 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) if (NetworkManager.PrefabHandler.ContainsHandler(networkObject)) { NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(networkObject); - OnDespawnObject(networkObjectId, false); + OnDespawnObject(networkObject, false); } else { @@ -710,7 +717,7 @@ internal void OnDespawnObject(ulong networkObjectId, bool destroyGameObject) // for some reason, we can get down here and SpawnedObjects for this // networkId will no longer be here, even as we check this at the start // of the function - if (SpawnedObjects.Remove(networkObjectId)) + if (SpawnedObjects.Remove(networkObject.NetworkObjectId)) { SpawnedObjectsList.Remove(networkObject); }