Skip to content

Commit f13dc28

Browse files
test
Adding tests to validate both of these fixes.
1 parent ad42901 commit f13dc28

File tree

3 files changed

+181
-0
lines changed

3 files changed

+181
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System.Collections;
2+
using System.Text.RegularExpressions;
3+
using NUnit.Framework;
4+
using Unity.Netcode.TestHelpers.Runtime;
5+
using UnityEngine;
6+
using UnityEngine.TestTools;
7+
8+
9+
namespace Unity.Netcode.RuntimeTests
10+
{
11+
[TestFixture(HostOrServer.Server)]
12+
[TestFixture(HostOrServer.Host)]
13+
internal class PlayerSpawnObjectVisibilityTests : NetcodeIntegrationTest
14+
{
15+
protected override int NumberOfClients => 0;
16+
17+
public enum PlayerSpawnStages
18+
{
19+
OnNetworkSpawn,
20+
OnNetworkPostSpawn,
21+
}
22+
23+
public PlayerSpawnObjectVisibilityTests(HostOrServer hostOrServer) : base(hostOrServer) { }
24+
25+
public class PlayerVisibilityTestComponent : NetworkBehaviour
26+
{
27+
public PlayerSpawnStages Stage;
28+
29+
private void Awake()
30+
{
31+
var networkObject = GetComponent<NetworkObject>();
32+
// Assure the player prefab will not spawn with observers.
33+
// This assures that when the server/host spawns the connecting client's
34+
// player prefab, the spawn object will initially not be spawnd on the client side.
35+
networkObject.SpawnWithObservers = false;
36+
}
37+
38+
public override void OnNetworkSpawn()
39+
{
40+
ShowToClient(PlayerSpawnStages.OnNetworkSpawn);
41+
base.OnNetworkSpawn();
42+
}
43+
44+
protected override void OnNetworkPostSpawn()
45+
{
46+
ShowToClient(PlayerSpawnStages.OnNetworkPostSpawn);
47+
base.OnNetworkPostSpawn();
48+
}
49+
50+
private void ShowToClient(PlayerSpawnStages currentStage)
51+
{
52+
if (!IsServer || Stage != currentStage)
53+
{
54+
return;
55+
}
56+
NetworkObject.NetworkShow(OwnerClientId);
57+
}
58+
}
59+
60+
protected override void OnCreatePlayerPrefab()
61+
{
62+
m_PlayerPrefab.AddComponent<PlayerVisibilityTestComponent>();
63+
base.OnCreatePlayerPrefab();
64+
}
65+
66+
/// <summary>
67+
/// Tests the scenario where under a client-server network topology if a player prefab
68+
/// is spawned by the server with no observers but the player prefab itself has server
69+
/// side script that will network show the spawned object to the owning client.
70+
///
71+
/// Because NetworkShow will defer the CreateObjectMessage until the late update, the
72+
/// server/host needs to filter out including anything within the synchronization
73+
/// message that already has pending visibility.
74+
/// </summary>
75+
/// <param name="spawnStage">Spawn stages to test</param>
76+
/// <returns>IEnumerator</returns>
77+
[UnityTest]
78+
public IEnumerator NetworkShowOnSpawnTest([Values] PlayerSpawnStages spawnStage)
79+
{
80+
m_PlayerPrefab.GetComponent<PlayerVisibilityTestComponent>().Stage = spawnStage;
81+
82+
yield return CreateAndStartNewClient();
83+
84+
yield return new WaitForSeconds(0.25f);
85+
86+
NetcodeLogAssert.LogWasNotReceived(LogType.Warning, new Regex("but it is already in the spawned list!"));
87+
var client = m_ClientNetworkManagers[0];
88+
Assert.True(client.LocalClient.PlayerObject != null, $"Client-{client.LocalClientId} does not have a player object!");
89+
}
90+
}
91+
}

com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/PlayerSpawnObjectVisibilityTests.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,5 +601,84 @@ public IEnumerator NetworkShowHideAroundListModify()
601601
Compare(ShowHideObject.ObjectsPerClientId[0].MyList, ShowHideObject.ObjectsPerClientId[2].MyList);
602602
}
603603
}
604+
605+
private GameObject m_OwnershipObject;
606+
private NetworkObject m_OwnershipNetworkObject;
607+
private NetworkManager m_NewOwner;
608+
private ulong m_ObjectId;
609+
610+
611+
private bool AllObjectsSpawnedOnClients()
612+
{
613+
foreach (var networkManager in m_ClientNetworkManagers)
614+
{
615+
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(m_OwnershipNetworkObject.NetworkObjectId))
616+
{
617+
return false;
618+
}
619+
}
620+
return true;
621+
}
622+
623+
private bool ObjectHiddenOnNonAuthorityClients()
624+
{
625+
foreach (var networkManager in m_ClientNetworkManagers)
626+
{
627+
if (networkManager.LocalClientId == m_OwnershipNetworkObject.OwnerClientId)
628+
{
629+
continue;
630+
}
631+
if (networkManager.SpawnManager.SpawnedObjects.ContainsKey(m_OwnershipNetworkObject.NetworkObjectId))
632+
{
633+
return false;
634+
}
635+
}
636+
return true;
637+
}
638+
639+
private bool OwnershipHasChanged()
640+
{
641+
if (!m_NewOwner.SpawnManager.SpawnedObjects.ContainsKey(m_ObjectId))
642+
{
643+
return false;
644+
}
645+
return m_NewOwner.SpawnManager.SpawnedObjects[m_ObjectId].OwnerClientId == m_NewOwner.LocalClientId;
646+
}
647+
648+
649+
[UnityTest]
650+
public IEnumerator NetworkShowAndChangeOwnership()
651+
{
652+
var authority = m_ServerNetworkManager;
653+
654+
m_OwnershipObject = SpawnObject(m_PrefabToSpawn, authority);
655+
m_OwnershipNetworkObject = m_OwnershipObject.GetComponent<NetworkObject>();
656+
657+
yield return WaitForConditionOrTimeOut(AllObjectsSpawnedOnClients);
658+
AssertOnTimeout("Timed out waiting for all clients to spawn the ownership object!");
659+
660+
VerboseDebug($"Hiding object {m_OwnershipNetworkObject.NetworkObjectId} on all clients");
661+
foreach (var client in m_ClientNetworkManagers)
662+
{
663+
m_OwnershipNetworkObject.NetworkHide(client.LocalClientId);
664+
}
665+
666+
yield return WaitForConditionOrTimeOut(ObjectHiddenOnNonAuthorityClients);
667+
AssertOnTimeout("Timed out waiting for all clients to hide the ownership object!");
668+
669+
m_NewOwner = m_ClientNetworkManagers[0];
670+
Assert.AreNotEqual(m_OwnershipNetworkObject.OwnerClientId, m_NewOwner.LocalClientId, $"Client-{m_NewOwner.LocalClientId} should not have ownership of object {m_OwnershipNetworkObject.NetworkObjectId}!");
671+
Assert.False(m_NewOwner.SpawnManager.SpawnedObjects.ContainsKey(m_OwnershipNetworkObject.NetworkObjectId), $"Client-{m_NewOwner.LocalClientId} should not have object {m_OwnershipNetworkObject.NetworkObjectId} spawned!");
672+
673+
// Run NetworkShow and ChangeOwnership directly after one-another
674+
VerboseDebug($"Calling {nameof(NetworkObject.NetworkShow)} on object {m_OwnershipNetworkObject.NetworkObjectId} for client {m_NewOwner.LocalClientId}");
675+
m_OwnershipNetworkObject.NetworkShow(m_NewOwner.LocalClientId);
676+
VerboseDebug($"Calling {nameof(NetworkObject.ChangeOwnership)} on object {m_OwnershipNetworkObject.NetworkObjectId} for client {m_NewOwner.LocalClientId}");
677+
m_OwnershipNetworkObject.ChangeOwnership(m_NewOwner.LocalClientId);
678+
m_ObjectId = m_OwnershipNetworkObject.NetworkObjectId;
679+
yield return WaitForConditionOrTimeOut(OwnershipHasChanged);
680+
AssertOnTimeout($"Timed out waiting for clients-{m_NewOwner.LocalClientId} to gain ownership of object {m_OwnershipNetworkObject.NetworkObjectId}!");
681+
VerboseDebug($"Client {m_NewOwner.LocalClientId} now owns object {m_OwnershipNetworkObject.NetworkObjectId}!");
682+
}
604683
}
605684
}

0 commit comments

Comments
 (0)