Skip to content

Commit 942747f

Browse files
test
adding validation test for the fix.
1 parent b096b06 commit 942747f

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

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

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
25
using NUnit.Framework;
36
using Unity.Netcode.TestHelpers.Runtime;
47
using UnityEngine;
@@ -184,4 +187,152 @@ public IEnumerator PlayerSpawnPosition()
184187
}
185188
}
186189
}
190+
191+
/// <summary>
192+
/// This test validates that when a player is spawned it has all observers
193+
/// properly set and the spawned and player object lists are properly populated.
194+
/// It also validates that when a player is despawned and the client is still connected
195+
/// that the client maintains its observers for other players.
196+
/// </summary>
197+
[TestFixture(HostOrServer.DAHost)]
198+
[TestFixture(HostOrServer.Host)]
199+
[TestFixture(HostOrServer.Server)]
200+
internal class PlayerSpawnAndDespawnTests : NetcodeIntegrationTest
201+
{
202+
protected override int NumberOfClients => 4;
203+
204+
private List<NetworkManager> m_NetworkManagers = new List<NetworkManager>();
205+
private StringBuilder m_ErrorLog = new StringBuilder();
206+
207+
public PlayerSpawnAndDespawnTests(HostOrServer hostOrServer) : base(hostOrServer) { }
208+
209+
protected override IEnumerator OnTearDown()
210+
{
211+
// Always clear in case test fails
212+
m_NetworkManagers.Clear();
213+
return base.OnTearDown();
214+
}
215+
216+
private bool ValidateObservers(ulong playerClientId, NetworkObject player)
217+
{
218+
foreach (var networkManager in m_NetworkManagers)
219+
{
220+
if (player != null && player.IsSpawned)
221+
{
222+
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(player.NetworkObjectId))
223+
{
224+
m_ErrorLog.AppendLine($"Client-{networkManager.LocalClientId} does not contain a spawned object entry {nameof(NetworkObject)}-{player.NetworkObjectId} for Client-{playerClientId}!");
225+
return false;
226+
}
227+
228+
var playerClone = networkManager.SpawnManager.SpawnedObjects[player.NetworkObjectId];
229+
foreach (var clientId in networkManager.ConnectedClientsIds)
230+
{
231+
if (!playerClone.IsNetworkVisibleTo(clientId))
232+
{
233+
m_ErrorLog.AppendLine($"Client-{networkManager.LocalClientId} failed visibility check for Client-{clientId} on {nameof(NetworkObject)}-{player.NetworkObjectId} for Client-{playerClientId}!");
234+
return false;
235+
}
236+
}
237+
238+
var foundPlayerClone = (NetworkObject)null;
239+
foreach (var playerObject in networkManager.SpawnManager.PlayerObjects)
240+
{
241+
if (playerObject.OwnerClientId == playerClientId && playerObject.NetworkObjectId == player.NetworkObjectId)
242+
{
243+
foundPlayerClone = playerObject;
244+
break;
245+
}
246+
}
247+
if (!foundPlayerClone)
248+
{
249+
m_ErrorLog.AppendLine($"Client-{networkManager.LocalClientId} does not contain a player entry for {nameof(NetworkObject)}-{player.NetworkObjectId} for Client-{playerClientId}!");
250+
return false;
251+
}
252+
253+
}
254+
else
255+
{
256+
// If the player client in question is despawned, then no NetworkManager instance
257+
// should contain a clone of that (or the client's NetworkManager instance as well)
258+
foreach (var playerClone in networkManager.SpawnManager.PlayerObjects)
259+
{
260+
if (playerClone.OwnerClientId == playerClientId)
261+
{
262+
m_ErrorLog.AppendLine($"Client-{networkManager.LocalClientId} contains a player {nameof(NetworkObject)}-{playerClone.NetworkObjectId} for Client-{playerClientId} when it should be despawned!");
263+
return false;
264+
}
265+
}
266+
}
267+
}
268+
return true;
269+
}
270+
271+
private bool ValidateAllClientPlayerObservers()
272+
{
273+
m_ErrorLog.Clear();
274+
foreach (var networkManager in m_NetworkManagers)
275+
{
276+
var spawnedOrNot = networkManager.LocalClient.PlayerObject == null ? "despawned" : "spawned";
277+
m_ErrorLog.AppendLine($"Validating Client-{networkManager.LocalClientId} {spawnedOrNot} player.");
278+
if (networkManager.LocalClient == null)
279+
{
280+
m_ErrorLog.AppendLine($"No {nameof(NetworkClient)} found for Client-{networkManager.LocalClientId}!");
281+
return false;
282+
}
283+
if (!ValidateObservers(networkManager.LocalClientId, networkManager.LocalClient.PlayerObject))
284+
{
285+
m_ErrorLog.AppendLine($"Client-{networkManager.LocalClientId} validation pass failed.");
286+
return false;
287+
}
288+
}
289+
return true;
290+
}
291+
292+
293+
[UnityTest]
294+
public IEnumerator PlayerSpawnDespawn()
295+
{
296+
if (m_ServerNetworkManager.IsHost)
297+
{
298+
m_NetworkManagers.Add(m_ServerNetworkManager);
299+
}
300+
m_NetworkManagers.AddRange(m_ClientNetworkManagers);
301+
302+
// Validate all observers are properly set with all players spawned
303+
yield return WaitForConditionOrTimeOut(ValidateAllClientPlayerObservers);
304+
AssertOnTimeout($"First Validation Failed:\n {m_ErrorLog}");
305+
var selectedClient = m_ClientNetworkManagers[Random.Range(0, m_ClientNetworkManagers.Count() - 1)];
306+
var playerSelected = selectedClient.LocalClient.PlayerObject;
307+
308+
if (m_DistributedAuthority)
309+
{
310+
playerSelected.Despawn(false);
311+
}
312+
else
313+
{
314+
m_ServerNetworkManager.SpawnManager.SpawnedObjects[playerSelected.NetworkObjectId].Despawn(false);
315+
}
316+
317+
// Validate all observers are properly set with one of the players despawned
318+
yield return WaitForConditionOrTimeOut(ValidateAllClientPlayerObservers);
319+
AssertOnTimeout($"Second Validation Failed:\n {m_ErrorLog}");
320+
321+
if (m_DistributedAuthority)
322+
{
323+
playerSelected.SpawnAsPlayerObject(selectedClient.LocalClientId, false);
324+
}
325+
else
326+
{
327+
var serverPlayerInstance = Object.Instantiate(m_ServerNetworkManager.NetworkConfig.PlayerPrefab);
328+
serverPlayerInstance.GetComponent<NetworkObject>().SpawnAsPlayerObject(selectedClient.LocalClientId, false);
329+
}
330+
331+
// Validate all observers are properly set when the client's player is respawned.
332+
yield return WaitForConditionOrTimeOut(ValidateAllClientPlayerObservers);
333+
AssertOnTimeout($"Third Validation Failed:\n {m_ErrorLog}");
334+
335+
m_NetworkManagers.Clear();
336+
}
337+
}
187338
}

0 commit comments

Comments
 (0)