Skip to content

Commit 101bf34

Browse files
fix: OnNetworkDespawn is not called on server side when a client disconnects [MTT-5120] (#2323)
* fix This prevents the issue (when just destroying the GameObject) where any NetworkBehaviour component(s) destroyed before the NetworkObject would not have OnNetworkDespawn invoked. * test Adding the test to validate this fix.
1 parent 8e348c1 commit 101bf34

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1515
- The default listen address of `UnityTransport` is now 0.0.0.0. (#2307)
1616

1717
### Fixed
18+
- Fixed server side issue where, depending upon component ordering, some NetworkBehaviour components might not have their OnNetworkDespawn method invoked if the client side disconnected. (#2323)
1819

1920
- Fixed an issue in `UnityTransport` where an exception would be thrown if starting a Relay host/server on WebGL. This exception should only be thrown if using direct connections (where WebGL can't act as a host/server). (#2321)
2021

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,12 @@ private void OnClientDisconnectFromServer(ulong clientId)
20822082
}
20832083
else
20842084
{
2085-
Destroy(playerObject.gameObject);
2085+
// Call despawn to assure NetworkBehaviour.OnNetworkDespawn is invoked
2086+
// on the server-side (when the client side disconnected).
2087+
// This prevents the issue (when just destroying the GameObject) where
2088+
// any NetworkBehaviour component(s) destroyed before the NetworkObject
2089+
// would not have OnNetworkDespawn invoked.
2090+
SpawnManager.DespawnObject(playerObject, true);
20862091
}
20872092
}
20882093
else

com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,20 @@ protected virtual void OnCreatePlayerPrefab()
241241
{
242242
}
243243

244+
/// <summary>
245+
/// Invoked immediately after the player prefab GameObject is created
246+
/// prior to adding a NetworkObject component
247+
/// </summary>
248+
protected virtual void OnPlayerPrefabGameObjectCreated()
249+
{
250+
}
251+
244252
private void CreatePlayerPrefab()
245253
{
246254
VerboseDebug($"Entering {nameof(CreatePlayerPrefab)}");
247255
// Create playerPrefab
248256
m_PlayerPrefab = new GameObject("Player");
257+
OnPlayerPrefabGameObjectCreated();
249258
NetworkObject networkObject = m_PlayerPrefab.AddComponent<NetworkObject>();
250259

251260
// Make it a prefab

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections;
22
using UnityEngine;
3+
using NUnit.Framework;
34
using UnityEngine.TestTools;
45
using Unity.Netcode.TestHelpers.Runtime;
56
using Unity.Netcode.Components;
@@ -147,5 +148,35 @@ public IEnumerator ValidateDeleteChildNetworkBehaviour()
147148
// (validating the fix)
148149
Object.Destroy(parentObject);
149150
}
151+
152+
protected override void OnPlayerPrefabGameObjectCreated()
153+
{
154+
// Adds the SimpleNetworkBehaviour before the NetworkObject
155+
// for OnNetworkDespawnInvokedWhenClientDisconnects testing
156+
m_PlayerPrefab.AddComponent<SimpleNetworkBehaviour>();
157+
}
158+
159+
/// <summary>
160+
/// This validates that upon a client disconnecting, the server-side
161+
/// client's player clone will invoke NetworkBehaviour.OnNetworkDespawn
162+
/// when the component precedes the NetworkObject component.(PR-2323)
163+
/// </summary>
164+
[UnityTest]
165+
public IEnumerator OnNetworkDespawnInvokedWhenClientDisconnects()
166+
{
167+
m_AllowServerToStart = true;
168+
169+
// Now just start the Host
170+
yield return StartServerAndClients();
171+
172+
// Now create and connect a new client
173+
yield return CreateAndStartNewClient();
174+
175+
var serverSidePlayer = m_PlayerNetworkObjects[NetworkManager.ServerClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent<SimpleNetworkBehaviour>();
176+
177+
yield return StopOneClient(m_ClientNetworkManagers[0]);
178+
179+
Assert.True(serverSidePlayer.OnNetworkDespawnCalled, $"Server-side player clone did not invoke OnNetworkDespawn!");
180+
}
150181
}
151182
}

0 commit comments

Comments
 (0)