Skip to content

Commit 14c26fe

Browse files
fix: player objects do not honor the DontDestroyWithOwner property [MTT-4458] (#2225)
* fix This fixes the issue with player objects not honoring the DontDestroyWithOwner property. The summary for DontDestroyWithOwner was incorrect. When true the NetworkObject's ownership is given back to the server. * test Adding a test to verify that when a client disconnects and the client's player object has DontDestroyWithOwner set to true that the NetworkObject's ownership is transferred back to the client.
1 parent bc08e65 commit 14c26fe

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

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

2222
### Fixed
2323

24+
- Fixed the issue where player objects were not taking the `DontDestroyWithOwner` property into consideration when a client disconnected. (#2225)
2425
- Fixed issue #1924 where `UnityTransport` would fail to restart after a first failure (even if what caused the initial failure was addressed). (#2220)
2526
- Fixed issue where `NetworkTransform.SetStateServerRpc` and `NetworkTransform.SetStateClientRpc` were not honoring local vs world space settings when applying the position and rotation. (#2203)
2627
- Fixed ILPP `TypeLoadException` on WebGL on MacOS Editor and potentially other platforms. (#2199)

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,13 +1944,20 @@ private void OnClientDisconnectFromServer(ulong clientId)
19441944
var playerObject = networkClient.PlayerObject;
19451945
if (playerObject != null)
19461946
{
1947-
if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].PlayerObject.GlobalObjectIdHash))
1947+
if (!playerObject.DontDestroyWithOwner)
19481948
{
1949-
PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].PlayerObject);
1949+
if (PrefabHandler.ContainsHandler(ConnectedClients[clientId].PlayerObject.GlobalObjectIdHash))
1950+
{
1951+
PrefabHandler.HandleNetworkPrefabDestroy(ConnectedClients[clientId].PlayerObject);
1952+
}
1953+
else
1954+
{
1955+
Destroy(playerObject.gameObject);
1956+
}
19501957
}
19511958
else
19521959
{
1953-
Destroy(playerObject.gameObject);
1960+
playerObject.RemoveOwnership();
19541961
}
19551962
}
19561963

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ internal void GenerateGlobalObjectIdHash()
129129

130130
/// <summary>
131131
/// Whether or not to destroy this object if it's owner is destroyed.
132-
/// If false, the objects ownership will be given to the server.
132+
/// If true, the objects ownership will be given to the server.
133133
/// </summary>
134134
public bool DontDestroyWithOwner;
135135

com.unity.netcode.gameobjects/Tests/Runtime/DisconnectTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,53 @@ private void OnClientDisconnectCallback(ulong obj)
6060
{
6161
m_ClientDisconnected = true;
6262
}
63+
64+
[UnityTest]
65+
public IEnumerator ClientDisconnectPlayerObjectCleanup()
66+
{
67+
// create server and client instances
68+
NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients);
69+
70+
// create prefab
71+
var gameObject = new GameObject("PlayerObject");
72+
var networkObject = gameObject.AddComponent<NetworkObject>();
73+
networkObject.DontDestroyWithOwner = true;
74+
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
75+
76+
server.NetworkConfig.PlayerPrefab = gameObject;
77+
78+
for (int i = 0; i < clients.Length; i++)
79+
{
80+
clients[i].NetworkConfig.PlayerPrefab = gameObject;
81+
}
82+
83+
// start server and connect clients
84+
NetcodeIntegrationTestHelpers.Start(false, server, clients);
85+
86+
// wait for connection on client side
87+
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients);
88+
89+
// wait for connection on server side
90+
yield return NetcodeIntegrationTestHelpers.WaitForClientConnectedToServer(server);
91+
92+
// disconnect the remote client
93+
m_ClientDisconnected = false;
94+
95+
server.OnClientDisconnectCallback += OnClientDisconnectCallback;
96+
97+
var serverSideClientPlayer = server.ConnectedClients[clients[0].LocalClientId].PlayerObject;
98+
99+
// Stopping the client is the same as the client disconnecting
100+
NetcodeIntegrationTestHelpers.StopOneClient(clients[0]);
101+
102+
var timeoutHelper = new TimeoutHelper();
103+
yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_ClientDisconnected, timeoutHelper);
104+
105+
// ensure the object was destroyed
106+
Assert.True(serverSideClientPlayer.IsOwnedByServer, $"The client's player object's ownership was not transferred back to the server!");
107+
108+
// cleanup
109+
NetcodeIntegrationTestHelpers.Destroy();
110+
}
63111
}
64112
}

0 commit comments

Comments
 (0)