Skip to content

Commit 311216b

Browse files
fix
This fixes most of the synchronization issues with using a distributed authority network topology and scene management is disabled. (There still is some form of issue with changing ownership when distributing objects)
1 parent 90f97fd commit 311216b

File tree

5 files changed

+69
-17
lines changed

5 files changed

+69
-17
lines changed

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,14 @@ internal NetworkClient AddClient(ulong clientId)
10011001
}
10021002

10031003
var distributedAuthority = NetworkManager.DistributedAuthorityMode;
1004+
1005+
// If not using DA return early or if using DA and scene management is disabled then exit early Since we use NetworkShow to spawn
1006+
// objects on the newly connected client side.
1007+
if (!distributedAuthority || distributedAuthority && !NetworkManager.NetworkConfig.EnableSceneManagement)
1008+
{
1009+
return networkClient;
1010+
}
1011+
10041012
var sessionOwnerId = NetworkManager.CurrentSessionOwner;
10051013
var isSessionOwner = NetworkManager.LocalClient.IsSessionOwner;
10061014
foreach (var networkObject in NetworkManager.SpawnManager.SpawnedObjectsList)

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,7 +2894,7 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
28942894
SyncObservers = syncObservers,
28952895
Observers = syncObservers ? Observers.ToArray() : null,
28962896
NetworkSceneHandle = NetworkSceneHandle,
2897-
Hash = HostCheckForGlobalObjectIdHashOverride(),
2897+
Hash = CheckForGlobalObjectIdHashOverride(),
28982898
OwnerObject = this,
28992899
TargetClientId = targetClientId
29002900
};
@@ -3246,14 +3246,14 @@ internal void UpdateForSceneChanges()
32463246
}
32473247

32483248
/// <summary>
3249-
/// Only applies to Host mode.
3249+
/// Only applies to Hosts or session owners (for now)
32503250
/// Will return the registered source NetworkPrefab's GlobalObjectIdHash if one exists.
32513251
/// Server and Clients will always return the NetworkObject's GlobalObjectIdHash.
32523252
/// </summary>
3253-
/// <returns></returns>
3254-
internal uint HostCheckForGlobalObjectIdHashOverride()
3253+
/// <returns>appropriate hash value</returns>
3254+
internal uint CheckForGlobalObjectIdHashOverride()
32553255
{
3256-
if (NetworkManager.IsServer)
3256+
if (NetworkManager.IsServer || (NetworkManager.DistributedAuthorityMode && NetworkManager.LocalClient.IsSessionOwner))
32573257
{
32583258
if (NetworkManager.PrefabHandler.ContainsHandler(this))
32593259
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private void HandleOwnershipChange(ref NetworkContext context)
332332
// Sanity check that we are not sending duplicated change ownership messages
333333
if (networkObject.OwnerClientId == OwnerClientId)
334334
{
335-
UnityEngine.Debug.LogError($"Unnecessary ownership changed message for {NetworkObjectId}.");
335+
UnityEngine.Debug.LogError($"Client-{context.SenderId} sent unnecessary ownership changed message for {NetworkObjectId}.");
336336
// Ignore the message
337337
return;
338338
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,23 @@ public void Handle(ref NetworkContext context)
5555
// Don't redistribute for the local instance
5656
if (ClientId != networkManager.LocalClientId)
5757
{
58+
// Synchronize the client with spawned objects (relative to each client)
59+
networkManager.SpawnManager.SynchronizeObjectsToNewlyJoinedClient(ClientId);
60+
61+
// Keeping for reference in case the above doesn't resolve for hidden objects (theoretically it should)
5862
// Show any NetworkObjects that are:
5963
// - Hidden from the session owner
6064
// - Owned by this client
6165
// - Has NetworkObject.SpawnWithObservers set to true (the default)
62-
if (!networkManager.LocalClient.IsSessionOwner)
63-
{
64-
networkManager.SpawnManager.ShowHiddenObjectsToNewlyJoinedClient(ClientId);
65-
}
66+
//if (!networkManager.LocalClient.IsSessionOwner)
67+
//{
68+
// networkManager.SpawnManager.ShowHiddenObjectsToNewlyJoinedClient(ClientId);
69+
//}
6670

6771
// We defer redistribution to the end of the NetworkUpdateStage.PostLateUpdate
6872
networkManager.RedistributeToClient = true;
6973
networkManager.ClientToRedistribute = ClientId;
70-
networkManager.TickToRedistribute = networkManager.ServerTime.Tick + 20;
74+
networkManager.TickToRedistribute = networkManager.ServerTime.Tick + (int)(0.5f * networkManager.NetworkConfig.TickRate);
7175
}
7276
}
7377
}

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

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,6 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
580580
{
581581
networkObject.ChildNetworkBehaviours[i].UpdateNetworkProperties();
582582
}
583-
584583
size = NetworkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, NetworkManager.ServerClientId);
585584
NetworkManager.NetworkMetrics.TrackOwnershipChangeSent(NetworkManager.LocalClientId, networkObject, size);
586585
}
@@ -1976,14 +1975,14 @@ internal void NotifyNetworkObjectsSynchronized()
19761975
/// synchronizing in order to "show" (spawn) anything that might be currently hidden from
19771976
/// the session owner.
19781977
/// </summary>
1978+
/// <remarks>
1979+
/// Replacement is: SynchronizeObjectsToNewlyJoinedClient
1980+
/// </remarks>
19791981
internal void ShowHiddenObjectsToNewlyJoinedClient(ulong newClientId)
19801982
{
1981-
if (!NetworkManager.DistributedAuthorityMode)
1983+
if (NetworkManager == null || NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer)
19821984
{
1983-
if (NetworkManager == null || !NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer)
1984-
{
1985-
Debug.LogWarning($"[Internal Error] {nameof(ShowHiddenObjectsToNewlyJoinedClient)} invoked while !");
1986-
}
1985+
Debug.LogWarning($"[Internal Error] {nameof(ShowHiddenObjectsToNewlyJoinedClient)} invoked while shutdown is in progress!");
19871986
return;
19881987
}
19891988

@@ -2019,5 +2018,46 @@ internal void ShowHiddenObjectsToNewlyJoinedClient(ulong newClientId)
20192018
}
20202019
}
20212020
}
2021+
2022+
internal void SynchronizeObjectsToNewlyJoinedClient(ulong newClientId)
2023+
{
2024+
if (NetworkManager == null || NetworkManager.ShutdownInProgress && NetworkManager.LogLevel <= LogLevel.Developer)
2025+
{
2026+
Debug.LogWarning($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} invoked while shutdown is in progress!");
2027+
return;
2028+
}
2029+
2030+
if (!NetworkManager.DistributedAuthorityMode)
2031+
{
2032+
Debug.LogError($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} should only be invoked when using a distributed authority network topology!");
2033+
return;
2034+
}
2035+
2036+
if (NetworkManager.NetworkConfig.EnableSceneManagement)
2037+
{
2038+
Debug.LogError($"[Internal Error] {nameof(SynchronizeObjectsToNewlyJoinedClient)} should only be invoked when scene management is disabled!");
2039+
return;
2040+
}
2041+
2042+
var localClientId = NetworkManager.LocalClient.ClientId;
2043+
foreach (var networkObject in SpawnedObjectsList)
2044+
{
2045+
if (networkObject.SpawnWithObservers && networkObject.OwnerClientId == localClientId)
2046+
{
2047+
if (networkObject.Observers.Contains(newClientId))
2048+
{
2049+
if (NetworkManager.LogLevel <= LogLevel.Developer)
2050+
{
2051+
// Temporary tracking to make sure we are not showing something already visibile (should never be the case for this)
2052+
Debug.LogWarning($"[{nameof(SynchronizeObjectsToNewlyJoinedClient)}][{networkObject.name}] New client as already an observer!");
2053+
}
2054+
// For now, remove the client (impossible for the new client to have an instance since the session owner doesn't) to make sure newly added
2055+
// code to handle this edge case works.
2056+
networkObject.Observers.Remove(newClientId);
2057+
}
2058+
networkObject.NetworkShow(newClientId);
2059+
}
2060+
}
2061+
}
20222062
}
20232063
}

0 commit comments

Comments
 (0)