Skip to content

Commit c877502

Browse files
fix
Fixing issue where spawning a player in distributed authority mode via a client, typically session owner, other than the newly connected client and scene management is disabled then the already spawned players will not properly get synchronized by each owning client due to the newly connected client's identifier already being added prior to synchronization.
1 parent 9bf917b commit c877502

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,15 @@ public void SetSceneObjectStatus(bool isSceneObject = false)
13201320

13211321
internal readonly HashSet<ulong> Observers = new HashSet<ulong>();
13221322

1323+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1324+
internal void AddObserver(ulong clientId)
1325+
{
1326+
#if NETCODE_DEBUG_OBSERVERS
1327+
Debug.Log($"[{nameof(NetworkObject)}][{name}-{NetworkObjectId}] Adding Client-{clientId} as an observer.");
1328+
#endif
1329+
Observers.Add(clientId);
1330+
}
1331+
13231332
#if MULTIPLAYER_TOOLS
13241333
private string m_CachedNameForMetrics;
13251334
#endif
@@ -1469,7 +1478,7 @@ public void NetworkShow(ulong clientId)
14691478
return;
14701479
}
14711480
NetworkManager.SpawnManager.MarkObjectForShowingTo(this, clientId);
1472-
Observers.Add(clientId);
1481+
AddObserver(clientId);
14731482
}
14741483

14751484

@@ -3326,7 +3335,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33263335
{
33273336
foreach (var observer in sceneObject.Observers)
33283337
{
3329-
networkObject.Observers.Add(observer);
3338+
networkObject.AddObserver(observer);
33303339
}
33313340
}
33323341

@@ -3346,11 +3355,11 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33463355
if (networkObject.IsPlayerObject)
33473356
{
33483357
// If it is another player, then make sure the local player is aware of the player
3349-
playerObject.Observers.Add(networkObject.OwnerClientId);
3358+
playerObject.AddObserver(networkObject.OwnerClientId);
33503359
}
33513360

33523361
// Assure the local player has observability
3353-
networkObject.Observers.Add(playerObject.OwnerClientId);
3362+
networkObject.AddObserver(playerObject.OwnerClientId);
33543363

33553364
// If it is a player object, then add it to all known spawned NetworkObjects that spawn with observers
33563365
if (networkObject.IsPlayerObject)
@@ -3359,7 +3368,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33593368
{
33603369
if (netObject.Value.SpawnWithObservers)
33613370
{
3362-
netObject.Value.Observers.Add(networkObject.OwnerClientId);
3371+
netObject.Value.AddObserver(networkObject.OwnerClientId);
33633372
}
33643373
}
33653374
}
@@ -3371,7 +3380,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33713380
// Add all known players to the observers list if they don't already exist
33723381
foreach (var player in networkManager.SpawnManager.PlayerObjects)
33733382
{
3374-
networkObject.Observers.Add(player.OwnerClientId);
3383+
networkObject.AddObserver(player.OwnerClientId);
33753384
}
33763385
}
33773386
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public void Serialize(FastBufferWriter writer, int targetVersion)
158158
{
159159
if (sobj.SpawnWithObservers && (sobj.CheckObjectVisibility == null || sobj.CheckObjectVisibility(OwnerClientId)))
160160
{
161-
sobj.Observers.Add(OwnerClientId);
161+
sobj.AddObserver(OwnerClientId);
162162
// In distributed authority mode, we send the currently known observers of each NetworkObject to the client being synchronized.
163163
var sceneObject = sobj.GetMessageSceneObject(OwnerClientId, IsDistributedAuthority);
164164
sceneObject.Serialize(writer);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ internal static void CreateObject(ref NetworkManager networkManager, ulong sende
208208
// Update the observers for this instance
209209
for (int i = 0; i < clientList.Count; i++)
210210
{
211-
networkObject.Observers.Add(clientList[i]);
211+
networkObject.AddObserver(clientList[i]);
212212
}
213213

214214
// Mock CMB Service and forward to all clients

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,33 @@ private void AddPlayerObject(NetworkObject playerObject)
8181
}
8282
}
8383

84+
var cmbService = NetworkManager.CMBServiceConnection;
85+
var sceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement;
86+
8487
foreach (var player in m_PlayerObjects)
8588
{
89+
// When connected to the CMB service, scene management is disabled, and it is the local player, we do
90+
// not want to add the newly connected player to the observers list of the local player as that will be
91+
// done when the local client shows the NetworkObject to the newly connected client.
92+
var shouldAddObserver = cmbService && !sceneManagement ? !player.IsLocalPlayer : true;
8693
// If the player's SpawnWithObservers is not set then do not add the new player object's owner as an observer.
87-
if (player.SpawnWithObservers)
94+
if (player.SpawnWithObservers && shouldAddObserver)
8895
{
89-
player.Observers.Add(playerObject.OwnerClientId);
96+
player.AddObserver(playerObject.OwnerClientId);
9097
}
9198

9299
// If the new player object's SpawnWithObservers is not set then do not add this player as an observer to the new player object.
93100
if (playerObject.SpawnWithObservers)
94101
{
95-
playerObject.Observers.Add(player.OwnerClientId);
102+
playerObject.AddObserver(player.OwnerClientId);
96103
}
97104
}
98105

99106
// Only if spawn with observers is set or we are using a distributed authority network topology and this is the client's player should we add
100107
// the owner as an observer.
101108
if (playerObject.SpawnWithObservers || (NetworkManager.DistributedAuthorityMode && NetworkManager.LocalClientId == playerObject.OwnerClientId))
102109
{
103-
playerObject.Observers.Add(playerObject.OwnerClientId);
110+
playerObject.AddObserver(playerObject.OwnerClientId);
104111
}
105112

106113
m_PlayerObjects.Add(playerObject);
@@ -1066,7 +1073,7 @@ internal void AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n
10661073
// (authority should not take into consideration networkObject.CheckObjectVisibility when SpawnWithObservers is false)
10671074
if (!networkObject.SpawnWithObservers)
10681075
{
1069-
networkObject.Observers.Add(ownerClientId);
1076+
networkObject.AddObserver(ownerClientId);
10701077
}
10711078
else
10721079
{
@@ -1077,15 +1084,15 @@ internal void AuthorityLocalSpawn([NotNull] NetworkObject networkObject, ulong n
10771084
{
10781085
continue;
10791086
}
1080-
networkObject.Observers.Add(clientId);
1087+
networkObject.AddObserver(clientId);
10811088
}
10821089

10831090
// Sanity check to make sure the owner is always included
10841091
// Itentionally checking as opposed to just assigning in order to generate notification.
10851092
if (!networkObject.Observers.Contains(ownerClientId))
10861093
{
10871094
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!");
1088-
networkObject.Observers.Add(ownerClientId);
1095+
networkObject.AddObserver(ownerClientId);
10891096
}
10901097
}
10911098
}
@@ -1174,7 +1181,7 @@ internal void SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
11741181
// If running as a server only, then make sure to always add the server's client identifier
11751182
if (!NetworkManager.IsHost)
11761183
{
1177-
networkObject.Observers.Add(NetworkManager.LocalClientId);
1184+
networkObject.AddObserver(NetworkManager.LocalClientId);
11781185
}
11791186

11801187
// Add client observers
@@ -1185,7 +1192,7 @@ internal void SpawnNetworkObjectLocallyCommon(NetworkObject networkObject, ulong
11851192
{
11861193
continue;
11871194
}
1188-
networkObject.Observers.Add(NetworkManager.ConnectedClientsIds[i]);
1195+
networkObject.AddObserver(NetworkManager.ConnectedClientsIds[i]);
11891196
}
11901197
}
11911198

@@ -1738,15 +1745,15 @@ internal void UpdateObservedNetworkObjects(ulong clientId)
17381745
// 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
17391746
if (!sobj.Observers.Contains(clientId) && (sobj.SpawnWithObservers || clientId == NetworkManager.ServerClientId))
17401747
{
1741-
sobj.Observers.Add(clientId);
1748+
sobj.AddObserver(clientId);
17421749
}
17431750
}
17441751
else
17451752
{
17461753
// CheckObject visibility overrides SpawnWithObservers under this condition
17471754
if (sobj.CheckObjectVisibility(clientId))
17481755
{
1749-
sobj.Observers.Add(clientId);
1756+
sobj.AddObserver(clientId);
17501757
}
17511758
else // Otherwise, if the observers contains the clientId (shouldn't happen) then remove it since CheckObjectVisibility returned false
17521759
{

0 commit comments

Comments
 (0)