Skip to content

Commit 6e9530e

Browse files
Merge branch 'develop-2.0.0' into feat/attachable-networkbehaviour-and-object-controller
2 parents 043b0e7 + 6b9f9b5 commit 6e9530e

27 files changed

+1223
-1062
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1919

2020
### Fixed
2121

22+
- Fixed synchronizing the destroyGameObject parameter to clients for InScenePlaced network objects. (#3514)
2223
- Fixed distributed authority related issue where enabling the `NetworkObject.DestroyWithScene` would cause errors when a destroying non-authority instances due to loading (single mode) or unloading scene events. (#3500)
2324

2425
### 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)
@@ -1179,18 +1159,13 @@ internal void OnClientDisconnectFromServer(ulong clientId)
11791159
// If destroying with owner, then always despawn and destroy (or defer destroying to prefab handler)
11801160
if (!ownedObject.DontDestroyWithOwner)
11811161
{
1182-
if (NetworkManager.PrefabHandler.ContainsHandler(ownedObject.GlobalObjectIdHash))
1162+
if (ownedObject.IsSpawned)
11831163
{
1184-
if (ownedObject.IsSpawned)
1185-
{
1186-
// Don't destroy (prefab handler will determine this, but always notify
1187-
NetworkManager.SpawnManager.DespawnObject(ownedObject, false, true);
1188-
}
1189-
NetworkManager.PrefabHandler.HandleNetworkPrefabDestroy(ownedObject);
1164+
NetworkManager.SpawnManager.DespawnObject(ownedObject, true, true);
11901165
}
11911166
else
11921167
{
1193-
NetworkManager.SpawnManager.DespawnObject(ownedObject, true, true);
1168+
Object.Destroy(ownedObject.gameObject);
11941169
}
11951170
}
11961171
else if (!NetworkManager.ShutdownInProgress)

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

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@ namespace Unity.Netcode
66
internal struct DestroyObjectMessage : INetworkMessage, INetworkSerializeByMemcpy
77
{
88
private const int k_OptimizeDestroyObjectMessage = 1;
9-
public int Version => k_OptimizeDestroyObjectMessage;
9+
private const int k_AllowDestroyGameInPlaced = 2;
10+
public int Version => k_AllowDestroyGameInPlaced;
1011

1112
private const string k_Name = "DestroyObjectMessage";
1213

1314
public ulong NetworkObjectId;
1415

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;
2016
private byte m_DestroyFlags;
2117

2218
internal int DeferredDespawnTick;
@@ -25,32 +21,29 @@ internal struct DestroyObjectMessage : INetworkMessage, INetworkSerializeByMemcp
2521

2622
internal bool IsDistributedAuthority;
2723

28-
private const byte k_ClientTargetedDestroy = 0x01;
29-
private const byte k_DeferredDespawn = 0x02;
30-
3124
internal bool IsTargetedDestroy
3225
{
33-
get => GetFlag(k_ClientTargetedDestroy);
26+
get => ByteUtility.GetBit(m_DestroyFlags, 0);
3427

35-
set => SetFlag(value, k_ClientTargetedDestroy);
28+
set => ByteUtility.SetBit(ref m_DestroyFlags, 0, value);
3629
}
3730

3831
private bool IsDeferredDespawn
3932
{
40-
get => GetFlag(k_DeferredDespawn);
33+
get => ByteUtility.GetBit(m_DestroyFlags, 1);
4134

42-
set => SetFlag(value, k_DeferredDespawn);
35+
set => ByteUtility.SetBit(ref m_DestroyFlags, 1, value);
4336
}
4437

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

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); }
46+
set => ByteUtility.SetBit(ref m_DestroyFlags, 2, value);
5447
}
5548

5649
public void Serialize(FastBufferWriter writer, int targetVersion)
@@ -74,6 +67,10 @@ public void Serialize(FastBufferWriter writer, int targetVersion)
7467
BytePacker.WriteValueBitPacked(writer, DeferredDespawnTick);
7568
}
7669
}
70+
else if (targetVersion >= k_AllowDestroyGameInPlaced)
71+
{
72+
writer.WriteByteSafe(m_DestroyFlags);
73+
}
7774

7875
if (targetVersion < k_OptimizeDestroyObjectMessage)
7976
{
@@ -103,10 +100,15 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
103100
ByteUnpacker.ReadValueBitPacked(reader, out DeferredDespawnTick);
104101
}
105102
}
103+
else if (receivedMessageVersion >= k_AllowDestroyGameInPlaced)
104+
{
105+
reader.ReadByteSafe(out m_DestroyFlags);
106+
}
106107

107108
if (receivedMessageVersion < k_OptimizeDestroyObjectMessage)
108109
{
109-
reader.ReadValueSafe(out DestroyGameObject);
110+
reader.ReadValueSafe(out bool destroyGameObject);
111+
DestroyGameObject = destroyGameObject;
110112
}
111113

112114
if (networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
@@ -169,7 +171,7 @@ public void Handle(ref NetworkContext context)
169171
}
170172

171173
// Otherwise just despawn the NetworkObject right now
172-
networkManager.SpawnManager.OnDespawnNonAuthorityObject(networkObject);
174+
networkManager.SpawnManager.OnDespawnNonAuthorityObject(networkObject, DestroyGameObject);
173175
networkManager.NetworkMetrics.TrackObjectDestroyReceived(context.SenderId, networkObject, context.MessageSize);
174176
}
175177

@@ -208,7 +210,7 @@ private void HandleDeferredDespawn(ref NetworkManager networkManager, ref Networ
208210
{
209211
networkObject.DeferredDespawnTick = DeferredDespawnTick;
210212
var hasCallback = networkObject.OnDeferredDespawnComplete != null;
211-
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback);
213+
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback, DestroyGameObject);
212214
}
213215
}
214216
}

com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ namespace Unity.Netcode
33
/// <summary>
44
/// The permission types for reading a var
55
/// </summary>
6+
/// <remarks>
7+
/// Only relevant when using the client/server network topology.
8+
/// In distributed authority mode everyone can always read.
9+
/// </remarks>
610
public enum NetworkVariableReadPermission
711
{
812
/// <summary>

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,13 +1280,7 @@ public SceneEventProgressStatus UnloadScene(Scene scene)
12801280
}
12811281
}
12821282

1283-
sceneEventProgress.LoadSceneMode = LoadSceneMode.Additive;
1284-
1285-
// Any NetworkObjects marked to not be destroyed with a scene and reside within the scene about to be unloaded
1286-
// should be migrated temporarily into the DDOL, once the scene is unloaded they will be migrated into the
1287-
// currently active scene.
12881283
var networkManager = NetworkManager;
1289-
SceneManagerHandler.MoveObjectsFromSceneToDontDestroyOnLoad(ref networkManager, scene);
12901284

12911285
var sceneEventData = BeginSceneEvent();
12921286
sceneEventData.SceneEventProgressId = sceneEventProgress.Guid;
@@ -1297,10 +1291,16 @@ public SceneEventProgressStatus UnloadScene(Scene scene)
12971291

12981292
// This will be the message we send to everyone when this scene event sceneEventProgress is complete
12991293
sceneEventProgress.SceneEventType = SceneEventType.UnloadEventCompleted;
1294+
sceneEventProgress.LoadSceneMode = LoadSceneMode.Additive;
13001295

13011296
sceneEventProgress.SceneEventId = sceneEventData.SceneEventId;
13021297
sceneEventProgress.OnSceneEventCompleted = OnSceneUnloaded;
13031298

1299+
// Any NetworkObjects marked to not be destroyed with a scene and reside within the scene about to be unloaded
1300+
// should be migrated temporarily into the DDOL, once the scene is unloaded they will be migrated into the
1301+
// currently active scene.
1302+
SceneManagerHandler.MoveObjectsFromSceneToDontDestroyOnLoad(ref networkManager, scene);
1303+
13041304
if (!RemoveServerClientSceneHandle(sceneEventData.SceneHandle, scene.handle))
13051305
{
13061306
Debug.LogError($"Failed to remove {SceneNameFromHash(sceneEventData.SceneHash)} scene handles [Server ({sceneEventData.SceneHandle})][Local({scene.handle})]");
@@ -2831,6 +2831,27 @@ internal bool IsSceneEventInProgress()
28312831
return false;
28322832
}
28332833

2834+
internal bool IsSceneUnloading(NetworkObject networkObject)
2835+
{
2836+
if (!NetworkManager.NetworkConfig.EnableSceneManagement)
2837+
{
2838+
return false;
2839+
}
2840+
2841+
foreach (var sceneEventEntry in SceneEventProgressTracking)
2842+
{
2843+
var name = SceneNameFromHash(sceneEventEntry.Value.SceneHash);
2844+
var scene = SceneManager.GetSceneByName(name);
2845+
var sameScene = name == networkObject.gameObject.scene.name && scene.handle == networkObject.SceneOriginHandle;
2846+
2847+
if (!sceneEventEntry.Value.HasTimedOut() && sceneEventEntry.Value.IsUnloading() && sceneEventEntry.Value.Status == SceneEventProgressStatus.Started && sameScene)
2848+
{
2849+
return true;
2850+
}
2851+
}
2852+
return false;
2853+
}
2854+
28342855
/// <summary>
28352856
/// Handles notifying clients when a NetworkObject has been migrated into a new scene
28362857
/// </summary>

com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventProgress.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,14 @@ internal void ClientFinishedSceneEvent(ulong clientId)
223223
}
224224
}
225225

226+
/// <summary>
227+
/// Returns whether the SceneEventType is related to an unloading event.
228+
/// </summary>
229+
internal bool IsUnloading()
230+
{
231+
return SceneEventType is SceneEventType.Unload or SceneEventType.UnloadComplete or SceneEventType.UnloadEventCompleted;
232+
}
233+
226234
/// <summary>
227235
/// Determines if the scene event has finished for both
228236
/// client(s) and server.

0 commit comments

Comments
 (0)