Skip to content

Commit 67621b2

Browse files
NoelStephensUnitymichalChrobot
authored andcommitted
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 d2d2db6 commit 67621b2

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

@@ -3340,7 +3349,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33403349
{
33413350
foreach (var observer in sceneObject.Observers)
33423351
{
3343-
networkObject.Observers.Add(observer);
3352+
networkObject.AddObserver(observer);
33443353
}
33453354
}
33463355

@@ -3360,11 +3369,11 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33603369
if (networkObject.IsPlayerObject)
33613370
{
33623371
// If it is another player, then make sure the local player is aware of the player
3363-
playerObject.Observers.Add(networkObject.OwnerClientId);
3372+
playerObject.AddObserver(networkObject.OwnerClientId);
33643373
}
33653374

33663375
// Assure the local player has observability
3367-
networkObject.Observers.Add(playerObject.OwnerClientId);
3376+
networkObject.AddObserver(playerObject.OwnerClientId);
33683377

33693378
// If it is a player object, then add it to all known spawned NetworkObjects that spawn with observers
33703379
if (networkObject.IsPlayerObject)
@@ -3373,7 +3382,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33733382
{
33743383
if (netObject.Value.SpawnWithObservers)
33753384
{
3376-
netObject.Value.Observers.Add(networkObject.OwnerClientId);
3385+
netObject.Value.AddObserver(networkObject.OwnerClientId);
33773386
}
33783387
}
33793388
}
@@ -3385,7 +3394,7 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
33853394
// Add all known players to the observers list if they don't already exist
33863395
foreach (var player in networkManager.SpawnManager.PlayerObjects)
33873396
{
3388-
networkObject.Observers.Add(player.OwnerClientId);
3397+
networkObject.AddObserver(player.OwnerClientId);
33893398
}
33903399
}
33913400
}

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)