Skip to content

Commit 7ffbe93

Browse files
committed
fix/mttb-1377/synchronize-despawn-to-client
1 parent f966e07 commit 7ffbe93

File tree

15 files changed

+612
-509
lines changed

15 files changed

+612
-509
lines changed

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

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Unity.Collections.LowLevel.Unsafe;
88
using Unity.Profiling;
99
using UnityEngine;
10+
using Object = UnityEngine.Object;
1011

1112
namespace Unity.Netcode
1213
{
@@ -1126,36 +1127,15 @@ internal void OnClientDisconnectFromServer(ulong clientId)
11261127
{
11271128
if (!playerObject.DontDestroyWithOwner)
11281129
{
1129-
// If a player NetworkObject is being despawned, make sure to remove all children if they are marked to not be destroyed
1130-
// with the owner.
1131-
if (NetworkManager.DAHost)
1132-
{
1133-
// Remove any children from the player object if they are not going to be destroyed with the owner
1134-
var childNetworkObjects = playerObject.GetComponentsInChildren<NetworkObject>();
1135-
foreach (var child in childNetworkObjects)
1136-
{
1137-
// TODO: We have always just removed all children, but we might think about changing this to preserve the nested child hierarchy.
1138-
if (child.DontDestroyWithOwner && child.transform.transform.parent)
1139-
{
1140-
// If we are here, then we are running in DAHost mode and have the authority to remove the child from its parent
1141-
child.AuthorityAppliedParenting = true;
1142-
child.TryRemoveParentCachedWorldPositionStays();
1143-
}
1144-
}
1145-
}
1146-
1147-
if (NetworkManager.PrefabHandler.ContainsHandler(playerObject.GlobalObjectIdHash))
1148-
{
1149-
// Despawn but don't destroy. DA Host will act like the service and send despawn notifications.
1150-
NetworkManager.SpawnManager.DespawnObject(playerObject, false, NetworkManager.DistributedAuthorityMode);
1151-
// Let the prefab handler determine if it will be destroyed
1152-
NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(playerObject);
1153-
}
1154-
else if (playerObject.IsSpawned)
1130+
if (playerObject.IsSpawned)
11551131
{
11561132
// Call despawn to assure NetworkBehaviour.OnNetworkDespawn is invoked on the server-side (when the client side disconnected).
11571133
// This prevents the issue (when just destroying the GameObject) where any NetworkBehaviour component(s) destroyed before the NetworkObject would not have OnNetworkDespawn invoked.
1158-
NetworkManager.SpawnManager.DespawnObject(playerObject, true, NetworkManager.DistributedAuthorityMode);
1134+
NetworkManager.SpawnManager.DespawnObject(playerObject, true, true);
1135+
}
1136+
else
1137+
{
1138+
Object.Destroy(playerObject.gameObject);
11591139
}
11601140
}
11611141
else if (!NetworkManager.ShutdownInProgress)
@@ -1180,18 +1160,13 @@ internal void OnClientDisconnectFromServer(ulong clientId)
11801160
// Handle an object with no observers other than the current disconnecting client as destroying with owner
11811161
if (!ownedObject.DontDestroyWithOwner && (ownedObject.Observers.Count == 0 || (ownedObject.Observers.Count == 1 && ownedObject.Observers.Contains(clientId))))
11821162
{
1183-
if (NetworkManager.PrefabHandler.ContainsHandler(ownedObject.GlobalObjectIdHash))
1163+
if (ownedObject.IsSpawned)
11841164
{
1185-
if (ownedObject.IsSpawned)
1186-
{
1187-
// Don't destroy (prefab handler will determine this, but always notify
1188-
NetworkManager.SpawnManager.DespawnObject(ownedObject, false, true);
1189-
}
1190-
NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(ownedObject);
1165+
NetworkManager.SpawnManager.DespawnObject(ownedObject, true, true);
11911166
}
11921167
else
11931168
{
1194-
NetworkManager.SpawnManager.DespawnObject(ownedObject, true, true);
1169+
Object.Destroy(ownedObject.gameObject);
11951170
}
11961171
}
11971172
else if (!NetworkManager.ShutdownInProgress)

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

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
using System.Linq;
22
using System.Runtime.CompilerServices;
3+
using UnityEngine;
34

45
namespace Unity.Netcode
56
{
67
internal struct DestroyObjectMessage : INetworkMessage, INetworkSerializeByMemcpy
78
{
89
private const int k_OptimizeDestroyObjectMessage = 1;
9-
public int Version => k_OptimizeDestroyObjectMessage;
10+
private const int k_AllowDestroyGameInPlaced = 2;
11+
public int Version => k_AllowDestroyGameInPlaced;
1012

1113
private const string k_Name = "DestroyObjectMessage";
1214

1315
public ulong NetworkObjectId;
1416

15-
/// <summary>
16-
/// Used to communicate whether to destroy the associated game object.
17-
/// Should be false if the object is InScenePlaced and true otherwise
18-
/// </summary>
19-
public bool DestroyGameObject;
2017
private byte m_DestroyFlags;
2118

2219
internal int DeferredDespawnTick;
@@ -25,32 +22,29 @@ internal struct DestroyObjectMessage : INetworkMessage, INetworkSerializeByMemcp
2522

2623
internal bool IsDistributedAuthority;
2724

28-
private const byte k_ClientTargetedDestroy = 0x01;
29-
private const byte k_DeferredDespawn = 0x02;
30-
3125
internal bool IsTargetedDestroy
3226
{
33-
get => GetFlag(k_ClientTargetedDestroy);
27+
get => ByteUtility.GetBit(m_DestroyFlags, 0);
3428

35-
set => SetFlag(value, k_ClientTargetedDestroy);
29+
set => ByteUtility.SetBit(ref m_DestroyFlags, 0, value);
3630
}
3731

3832
private bool IsDeferredDespawn
3933
{
40-
get => GetFlag(k_DeferredDespawn);
34+
get => ByteUtility.GetBit(m_DestroyFlags, 1);
4135

42-
set => SetFlag(value, k_DeferredDespawn);
36+
set => ByteUtility.SetBit(ref m_DestroyFlags, 1, value);
4337
}
4438

45-
private bool GetFlag(int flag)
39+
/// <summary>
40+
/// Used to communicate whether to destroy the associated game object.
41+
/// Should be false if the object is InScenePlaced and true otherwise
42+
/// </summary>
43+
public bool DestroyGameObject
4644
{
47-
return (m_DestroyFlags & flag) != 0;
48-
}
45+
get => ByteUtility.GetBit(m_DestroyFlags, 2);
4946

50-
private void SetFlag(bool set, byte flag)
51-
{
52-
if (set) { m_DestroyFlags = (byte)(m_DestroyFlags | flag); }
53-
else { m_DestroyFlags = (byte)(m_DestroyFlags & ~flag); }
47+
set => ByteUtility.SetBit(ref m_DestroyFlags, 2, value);
5448
}
5549

5650
public void Serialize(FastBufferWriter writer, int targetVersion)
@@ -73,6 +67,9 @@ public void Serialize(FastBufferWriter writer, int targetVersion)
7367
{
7468
BytePacker.WriteValueBitPacked(writer, DeferredDespawnTick);
7569
}
70+
} else if (targetVersion >= k_AllowDestroyGameInPlaced)
71+
{
72+
writer.WriteByteSafe(m_DestroyFlags);
7673
}
7774

7875
if (targetVersion < k_OptimizeDestroyObjectMessage)
@@ -102,11 +99,15 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
10299
{
103100
ByteUnpacker.ReadValueBitPacked(reader, out DeferredDespawnTick);
104101
}
102+
} else if (receivedMessageVersion >= k_AllowDestroyGameInPlaced)
103+
{
104+
reader.ReadByteSafe(out m_DestroyFlags);
105105
}
106106

107107
if (receivedMessageVersion < k_OptimizeDestroyObjectMessage)
108108
{
109-
reader.ReadValueSafe(out DestroyGameObject);
109+
reader.ReadValueSafe(out bool destroyGameObject);
110+
DestroyGameObject = destroyGameObject;
110111
}
111112

112113
if (networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
@@ -169,7 +170,7 @@ public void Handle(ref NetworkContext context)
169170
}
170171

171172
// Otherwise just despawn the NetworkObject right now
172-
networkManager.SpawnManager.OnDespawnNonAuthorityObject(networkObject);
173+
networkManager.SpawnManager.OnDespawnNonAuthorityObject(networkObject, DestroyGameObject);
173174
networkManager.NetworkMetrics.TrackObjectDestroyReceived(context.SenderId, networkObject, context.MessageSize);
174175
}
175176

@@ -208,7 +209,7 @@ private void HandleDeferredDespawn(ref NetworkManager networkManager, ref Networ
208209
{
209210
networkObject.DeferredDespawnTick = DeferredDespawnTick;
210211
var hasCallback = networkObject.OnDeferredDespawnComplete != null;
211-
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback);
212+
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback, DestroyGameObject);
212213
}
213214
}
214215
}

0 commit comments

Comments
 (0)