diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index faa97b87ff..66f1a67e3b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -313,11 +313,11 @@ internal void NetworkTransformRegistration(NetworkObject networkObject, bool onU private void UpdateTopology() { - var transportTopology = IsListening ? NetworkConfig.NetworkTransport.CurrentTopology() : NetworkConfig.NetworkTopology; + var transportTopology = IsListening && IsConnectedClient ? NetworkConfig.NetworkTransport.CurrentTopology() : NetworkConfig.NetworkTopology; if (transportTopology != NetworkConfig.NetworkTopology) { - NetworkLog.LogErrorServer($"[Topology Mismatch] Transport detected an issue with the topology ({transportTopology} | {NetworkConfig.NetworkTopology}) usage or setting! Disconnecting from session."); - Shutdown(); + NetworkLog.LogErrorServer($"[Topology Mismatch][{transportTopology}:{transportTopology.GetType().Name}][NetworkManager.NetworkConfig:{NetworkConfig.NetworkTopology}] Transport detected an issue with the topology usage or setting! Disconnecting from session."); + Shutdown(true); } else { @@ -504,6 +504,7 @@ public void NetworkUpdate(NetworkUpdateStage updateStage) ShutdownInternal(); } } + } break; } diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index 608d5360d3..cbcd40ed4d 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -1320,6 +1320,15 @@ public void SetSceneObjectStatus(bool isSceneObject = false) internal readonly HashSet Observers = new HashSet(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void AddObserver(ulong clientId) + { +#if NETCODE_DEBUG_OBSERVERS + Debug.Log($"[{nameof(NetworkObject)}][{name}-{NetworkObjectId}] Adding Client-{clientId} as an observer."); +#endif + Observers.Add(clientId); + } + #if MULTIPLAYER_TOOLS private string m_CachedNameForMetrics; #endif @@ -1469,7 +1478,7 @@ public void NetworkShow(ulong clientId) return; } NetworkManager.SpawnManager.MarkObjectForShowingTo(this, clientId); - Observers.Add(clientId); + AddObserver(clientId); } @@ -3346,7 +3355,7 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject, { foreach (var observer in serializedObject.Observers) { - networkObject.Observers.Add(observer); + networkObject.AddObserver(observer); } } @@ -3366,11 +3375,11 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject, if (networkObject.IsPlayerObject) { // If it is another player, then make sure the local player is aware of the player - playerObject.Observers.Add(networkObject.OwnerClientId); + playerObject.AddObserver(networkObject.OwnerClientId); } // Assure the local player has observability - networkObject.Observers.Add(playerObject.OwnerClientId); + networkObject.AddObserver(playerObject.OwnerClientId); // If it is a player object, then add it to all known spawned NetworkObjects that spawn with observers if (networkObject.IsPlayerObject) @@ -3379,7 +3388,7 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject, { if (netObject.Value.SpawnWithObservers) { - netObject.Value.Observers.Add(networkObject.OwnerClientId); + netObject.Value.AddObserver(networkObject.OwnerClientId); } } } @@ -3391,7 +3400,7 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject, // Add all known players to the observers list if they don't already exist foreach (var player in networkManager.SpawnManager.PlayerObjects) { - networkObject.Observers.Add(player.OwnerClientId); + networkObject.AddObserver(player.OwnerClientId); } } } diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs index 5a1c5899cc..ab6a0ea042 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs @@ -158,7 +158,7 @@ public void Serialize(FastBufferWriter writer, int targetVersion) { if (sobj.SpawnWithObservers && (sobj.CheckObjectVisibility == null || sobj.CheckObjectVisibility(OwnerClientId))) { - sobj.Observers.Add(OwnerClientId); + sobj.AddObserver(OwnerClientId); // In distributed authority mode, we send the currently known observers of each NetworkObject to the client being synchronized. var serializedObject = sobj.Serialize(OwnerClientId, IsDistributedAuthority); serializedObject.Serialize(writer); diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/CreateObjectMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/CreateObjectMessage.cs index 475ba0b171..cf518a6216 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/CreateObjectMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/CreateObjectMessage.cs @@ -208,7 +208,7 @@ internal static void CreateObject(ref NetworkManager networkManager, ulong sende // Update the observers for this instance for (int i = 0; i < clientList.Count; i++) { - networkObject.Observers.Add(clientList[i]); + networkObject.AddObserver(clientList[i]); } // Mock CMB Service and forward to all clients diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs index 75dcc83ec3..c157c68cea 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs @@ -81,18 +81,25 @@ private void AddPlayerObject(NetworkObject playerObject) } } + var cmbService = NetworkManager.CMBServiceConnection; + var sceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement; + foreach (var player in m_PlayerObjects) { + // When connected to the CMB service, scene management is disabled, and it is the local player, we do + // not want to add the newly connected player to the observers list of the local player as that will be + // done when the local client shows the NetworkObject to the newly connected client. + var shouldAddObserver = cmbService && !sceneManagement ? !player.IsLocalPlayer : true; // If the player's SpawnWithObservers is not set then do not add the new player object's owner as an observer. - if (player.SpawnWithObservers) + if (player.SpawnWithObservers && shouldAddObserver) { - player.Observers.Add(playerObject.OwnerClientId); + player.AddObserver(playerObject.OwnerClientId); } // If the new player object's SpawnWithObservers is not set then do not add this player as an observer to the new player object. if (playerObject.SpawnWithObservers) { - playerObject.Observers.Add(player.OwnerClientId); + playerObject.AddObserver(player.OwnerClientId); } } @@ -100,7 +107,7 @@ private void AddPlayerObject(NetworkObject playerObject) // the owner as an observer. if (playerObject.SpawnWithObservers || (NetworkManager.DistributedAuthorityMode && NetworkManager.LocalClientId == playerObject.OwnerClientId)) { - playerObject.Observers.Add(playerObject.OwnerClientId); + playerObject.AddObserver(playerObject.OwnerClientId); } m_PlayerObjects.Add(playerObject); @@ -1066,7 +1073,7 @@ internal void AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n // (authority should not take into consideration networkObject.CheckObjectVisibility when SpawnWithObservers is false) if (!networkObject.SpawnWithObservers) { - networkObject.Observers.Add(ownerClientId); + networkObject.AddObserver(ownerClientId); } else { @@ -1077,7 +1084,7 @@ internal void AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n { continue; } - networkObject.Observers.Add(clientId); + networkObject.AddObserver(clientId); } // Sanity check to make sure the owner is always included @@ -1085,7 +1092,7 @@ internal void AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n if (!networkObject.Observers.Contains(ownerClientId)) { Debug.LogError($"Client-{ownerClientId} is the owner of {networkObject.name} but is not an observer! Adding owner, but there is a bug in observer synchronization!"); - networkObject.Observers.Add(ownerClientId); + networkObject.AddObserver(ownerClientId); } } } @@ -1174,7 +1181,7 @@ internal void SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong // If running as a server only, then make sure to always add the server's client identifier if (!NetworkManager.IsHost) { - networkObject.Observers.Add(NetworkManager.LocalClientId); + networkObject.AddObserver(NetworkManager.LocalClientId); } // Add client observers @@ -1185,7 +1192,7 @@ internal void SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong { continue; } - networkObject.Observers.Add(NetworkManager.ConnectedClientsIds[i]); + networkObject.AddObserver(NetworkManager.ConnectedClientsIds[i]); } } @@ -1738,7 +1745,7 @@ internal void UpdateObservedNetworkObjects(ulong clientId) // If the client is not part of the observers and spawn with observers is enabled on this instance or the clientId is the server/host/DAHost if (!sobj.Observers.Contains(clientId) && (sobj.SpawnWithObservers || clientId == NetworkManager.ServerClientId)) { - sobj.Observers.Add(clientId); + sobj.AddObserver(clientId); } } else @@ -1746,7 +1753,7 @@ internal void UpdateObservedNetworkObjects(ulong clientId) // CheckObject visibility overrides SpawnWithObservers under this condition if (sobj.CheckObjectVisibility(clientId)) { - sobj.Observers.Add(clientId); + sobj.AddObserver(clientId); } else // Otherwise, if the observers contains the clientId (shouldn't happen) then remove it since CheckObjectVisibility returned false {