Skip to content

Commit 27b6282

Browse files
committed
chore: [2.x] NetworkTransform parenting test
1 parent e3189a2 commit 27b6282

File tree

11 files changed

+216
-73
lines changed

11 files changed

+216
-73
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,14 +466,24 @@ private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetw
466466
/// CreateAndStartNewClient Only
467467
/// Invoked when the newly created client has been created
468468
/// </summary>
469+
/// <param name="networkManager">The NetworkManager instance of the client.</param>
469470
protected virtual void OnNewClientCreated(NetworkManager networkManager)
470471
{
472+
// Ensure any late joining client has all NetworkPrefabs required to connect.
473+
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
474+
{
475+
if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab))
476+
{
477+
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
478+
}
479+
}
471480
}
472481

473482
/// <summary>
474483
/// CreateAndStartNewClient Only
475484
/// Invoked when the newly created client has been created and started
476485
/// </summary>
486+
/// <param name="networkManager">The NetworkManager instance of the client.</param>
477487
protected virtual void OnNewClientStarted(NetworkManager networkManager)
478488
{
479489
}
@@ -483,6 +493,7 @@ protected virtual void OnNewClientStarted(NetworkManager networkManager)
483493
/// Invoked when the newly created client has been created, started, and connected
484494
/// to the server-host.
485495
/// </summary>
496+
/// <param name="networkManager">The NetworkManager instance of the client.</param>
486497
protected virtual void OnNewClientStartedAndConnected(NetworkManager networkManager)
487498
{
488499
}
@@ -494,6 +505,8 @@ protected virtual void OnNewClientStartedAndConnected(NetworkManager networkMana
494505
/// <remarks>
495506
/// Use this for testing connection and disconnection scenarios
496507
/// </remarks>
508+
/// <param name="networkManager">The NetworkManager instance of the client.</param>
509+
/// <returns>True if the test should wait for the client to connect; otherwise, false.</returns>
497510
protected virtual bool ShouldWaitForNewClientToConnect(NetworkManager networkManager)
498511
{
499512
return true;
@@ -503,6 +516,7 @@ protected virtual bool ShouldWaitForNewClientToConnect(NetworkManager networkMan
503516
/// This will create, start, and connect a new client while in the middle of an
504517
/// integration test.
505518
/// </summary>
519+
/// <returns>An IEnumerator to be used in a coroutine for asynchronous execution.</returns>
506520
protected IEnumerator CreateAndStartNewClient()
507521
{
508522
var networkManager = NetcodeIntegrationTestHelpers.CreateNewClient(m_ClientNetworkManagers.Length, m_EnableTimeTravel);

com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectOnSpawnTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,6 @@ private bool CheckClientsSideObserverTestObj()
8686
/// </summary>
8787
protected override void OnNewClientCreated(NetworkManager networkManager)
8888
{
89-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
90-
{
91-
if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab))
92-
{
93-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
94-
}
95-
}
9689
networkManager.NetworkConfig.EnableSceneManagement = m_ServerNetworkManager.NetworkConfig.EnableSceneManagement;
9790
base.OnNewClientCreated(networkManager);
9891
}

com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,17 @@ protected override void OnServerAndClientsCreated()
8181

8282
protected override void OnNewClientCreated(NetworkManager networkManager)
8383
{
84+
// Setup late joining client prefabs first
85+
base.OnNewClientCreated(networkManager);
86+
8487
networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
8588
networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety;
86-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
87-
{
88-
// To simulate a failure, we exclude the m_InValidNetworkPrefab from the connecting
89-
// client's side.
90-
if (networkPrefab.Prefab.name != m_InValidNetworkPrefab.name)
91-
{
92-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
93-
}
94-
}
89+
9590
// Disable forcing the same prefabs to avoid failed connections
9691
networkManager.NetworkConfig.ForceSamePrefabs = false;
9792
networkManager.LogLevel = m_CurrentLogLevel;
98-
base.OnNewClientCreated(networkManager);
93+
// To simulate a failure, exclude the m_InValidNetworkPrefab from the connecting client's side.
94+
networkManager.NetworkConfig.Prefabs.Remove(m_InValidNetworkPrefab);
9995
}
10096

10197
[UnityTest]

com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOwnershipTests.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,6 @@ protected override void OnServerAndClientsCreated()
9191
base.OnServerAndClientsCreated();
9292
}
9393

94-
/// <summary>
95-
/// Clients created during a test need to have their prefabs list updated to
96-
/// match the server's prefab list.
97-
/// </summary>
98-
protected override void OnNewClientCreated(NetworkManager networkManager)
99-
{
100-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
101-
{
102-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
103-
}
104-
105-
base.OnNewClientCreated(networkManager);
106-
}
107-
10894
private bool ClientIsOwner()
10995
{
11096
var clientId = m_ClientNetworkManagers[0].LocalClientId;
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
using System.Collections;
2+
using Unity.Netcode.Components;
3+
using Unity.Netcode.TestHelpers.Runtime;
4+
using UnityEngine;
5+
using UnityEngine.TestTools;
6+
7+
namespace Unity.Netcode.RuntimeTests
8+
{
9+
internal class NetworkTransformParentingTests : IntegrationTestWithApproximation
10+
{
11+
/// <summary>
12+
/// A NetworkBehaviour that moves in space.
13+
/// When spawned on the client, an RPC is sent to the server to spawn a player object for that client.
14+
/// The server parents the player object to the spawner object. This gives a moving parent object and a non-moving child object.
15+
/// The child object should always be at {0,0,0} local space, while the parent object moves around.
16+
/// This NetworkBehaviour tests that parenting to a moving object works as expected.
17+
/// </summary>
18+
internal class PlayerSpawner : NetworkBehaviour
19+
{
20+
/// <summary>
21+
/// Prefab for the player
22+
/// </summary>
23+
public NetworkObject playerPrefab;
24+
25+
/// <summary>
26+
/// The server side NetworkObject that was spawned when the client connected.
27+
/// </summary>
28+
public NetworkObject spawnedPlayer;
29+
30+
/// <summary>
31+
/// Represents the different movement states of the PlayerSpawner during the test lifecycle.
32+
/// </summary>
33+
public enum MoveState
34+
{
35+
// Initial state, PlayerSpawner will move without counting frames
36+
NotStarted,
37+
// The player object has been spawned, start counting frames
38+
PlayerSpawned,
39+
// We have moved far enough to test location
40+
ReachedPeak,
41+
}
42+
public MoveState moveState = MoveState.NotStarted;
43+
44+
// A count of the number of updates since the player object was spawned.
45+
private int m_Count;
46+
47+
// Movement offsets and targets.
48+
private const float k_PositionOffset = 5.0f;
49+
private const float k_RotationOffset = 25.0f;
50+
private readonly Vector3 m_PositionTarget = Vector3.one * k_PositionOffset * 10;
51+
private readonly Vector3 m_RotationTarget = Vector3.one * k_RotationOffset * 10;
52+
53+
private void Update()
54+
{
55+
if (!IsServer)
56+
{
57+
return;
58+
}
59+
60+
transform.position = Vector3.Lerp(transform.position, m_PositionTarget, Time.deltaTime * 2);
61+
var rotation = transform.rotation;
62+
rotation.eulerAngles = Vector3.Slerp(rotation.eulerAngles, m_RotationTarget, Time.deltaTime * 2);
63+
transform.rotation = rotation;
64+
65+
if (moveState != MoveState.PlayerSpawned)
66+
{
67+
return;
68+
}
69+
70+
// Move self for some time after player object is spawned
71+
// This ensures the parent object is moving throughout the spawn process.
72+
m_Count++;
73+
if (m_Count > 10)
74+
{
75+
// Mark PlayerSpawner as having moved far enough to test.
76+
moveState = MoveState.ReachedPeak;
77+
}
78+
}
79+
80+
public override void OnNetworkSpawn()
81+
{
82+
if (IsOwner)
83+
{
84+
// Owner initialises PlayerSpawner movement on spawn
85+
transform.position = Vector3.one * k_PositionOffset;
86+
var rotation = transform.rotation;
87+
rotation.eulerAngles = Vector3.one * k_RotationOffset;
88+
transform.rotation = rotation;
89+
}
90+
else
91+
{
92+
// When spawned on a client, send the RPC to spawn the player object
93+
// Using an RPC ensures the PlayerSpawner is moving for the entire spawning of the player object.
94+
RequestPlayerObjectSpawnServerRpc();
95+
}
96+
}
97+
98+
/// <summary>
99+
/// A ServerRpc that requests the server to spawn a player object for the client that invoked this RPC.
100+
/// </summary>
101+
/// <param name="rpcParams">Parameters for the ServerRpc, including the sender's client ID.</param>
102+
[ServerRpc(RequireOwnership = false)]
103+
private void RequestPlayerObjectSpawnServerRpc(ServerRpcParams rpcParams = default)
104+
{
105+
spawnedPlayer = Instantiate(playerPrefab);
106+
spawnedPlayer.SpawnAsPlayerObject(rpcParams.Receive.SenderClientId);
107+
spawnedPlayer.TrySetParent(NetworkObject, false);
108+
moveState = MoveState.PlayerSpawned;
109+
}
110+
}
111+
112+
// Client Authoritative NetworkTransform
113+
internal class ClientNetworkTransform : NetworkTransform
114+
{
115+
protected override bool OnIsServerAuthoritative()
116+
{
117+
return false;
118+
}
119+
}
120+
121+
// Don't start with any clients, we will manually spawn a client inside the test
122+
protected override int NumberOfClients => 0;
123+
124+
// Parent prefab with moving PlayerSpawner which will spawn the childPrefab
125+
private GameObject m_PlayerSpawnerPrefab;
126+
127+
// Client and server instances
128+
private PlayerSpawner m_ServerPlayerSpawner;
129+
private NetworkObject m_NewClientPlayer;
130+
131+
protected override void OnServerAndClientsCreated()
132+
{
133+
m_PlayerSpawnerPrefab = CreateNetworkObjectPrefab("Parent");
134+
var parentPlayerSpawner = m_PlayerSpawnerPrefab.AddComponent<PlayerSpawner>();
135+
m_PlayerSpawnerPrefab.AddComponent<NetworkTransform>();
136+
137+
var playerPrefab = CreateNetworkObjectPrefab("Child");
138+
var childNetworkTransform = playerPrefab.AddComponent<ClientNetworkTransform>();
139+
childNetworkTransform.InLocalSpace = true;
140+
141+
parentPlayerSpawner.playerPrefab = playerPrefab.GetComponent<NetworkObject>();
142+
143+
base.OnServerAndClientsCreated();
144+
}
145+
146+
private bool NewPlayerObjectSpawned()
147+
{
148+
return m_ServerPlayerSpawner.spawnedPlayer &&
149+
m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects.ContainsKey(m_ServerPlayerSpawner.spawnedPlayer.NetworkObjectId);
150+
}
151+
152+
private bool HasServerInstanceReachedPeakPoint()
153+
{
154+
VerboseDebug($"Client Local: {m_NewClientPlayer.transform.localPosition} Server Local: {m_ServerPlayerSpawner.spawnedPlayer.transform.localPosition}");
155+
return m_ServerPlayerSpawner.moveState == PlayerSpawner.MoveState.ReachedPeak;
156+
}
157+
158+
private bool ServerClientPositionMatches()
159+
{
160+
return Approximately(m_NewClientPlayer.transform.localPosition, m_ServerPlayerSpawner.spawnedPlayer.transform.localPosition) &&
161+
Approximately(m_NewClientPlayer.transform.position, m_ServerPlayerSpawner.spawnedPlayer.transform.position);
162+
}
163+
164+
[UnityTest]
165+
public IEnumerator TestParentedPlayerUsingLocalSpace()
166+
{
167+
// Spawn the PlayerSpawner object and save the instantiated component
168+
// The PlayerSpawner object will start moving.
169+
m_ServerPlayerSpawner = SpawnObject(m_PlayerSpawnerPrefab, m_ServerNetworkManager).GetComponent<PlayerSpawner>();
170+
171+
// Create a new client and connect to the server
172+
// The client will prompt the server to spawn a player object and parent it to the PlayerSpawner object.
173+
yield return CreateAndStartNewClient();
174+
175+
yield return WaitForConditionOrTimeOut(NewPlayerObjectSpawned);
176+
AssertOnTimeout($"Client did not spawn new player object!");
177+
178+
// Save the spawned player object
179+
m_NewClientPlayer = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects[m_ServerPlayerSpawner.spawnedPlayer.NetworkObjectId];
180+
181+
// Let the parent PlayerSpawner move for several ticks to get an offset
182+
yield return WaitForConditionOrTimeOut(HasServerInstanceReachedPeakPoint);
183+
AssertOnTimeout($"Server instance never reached peak point!");
184+
185+
// Check that the client and server local positions match (they should both be at {0,0,0} local space)
186+
yield return WaitForConditionOrTimeOut(ServerClientPositionMatches);
187+
AssertOnTimeout($"Client local position {m_NewClientPlayer.transform.localPosition} does not match" +
188+
$" server local position {m_ServerPlayerSpawner.spawnedPlayer.transform.localPosition}");
189+
}
190+
}
191+
}

com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformParentingTests.cs.meta

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

pvpExceptions.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,6 @@
238238
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: void OneTimeSetup(): undocumented",
239239
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator OnSetup(): missing <returns>",
240240
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator SetUp(): undocumented",
241-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: void OnNewClientCreated(NetworkManager): missing <param name=\"networkManager\">",
242-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: void OnNewClientStarted(NetworkManager): missing <param name=\"networkManager\">",
243-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: void OnNewClientStartedAndConnected(NetworkManager): missing <param name=\"networkManager\">",
244-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: bool ShouldWaitForNewClientToConnect(NetworkManager): missing <param name=\"networkManager\">",
245-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: bool ShouldWaitForNewClientToConnect(NetworkManager): missing <returns>",
246-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator CreateAndStartNewClient(): missing <returns>",
247241
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator StopOneClient(NetworkManager, bool): missing <param name=\"networkManager\">",
248242
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator StopOneClient(NetworkManager, bool): missing <param name=\"destroy\">",
249243
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTest: IEnumerator StopOneClient(NetworkManager, bool): missing <returns>",

testproject/Assets/Tests/Runtime/NetworkManagerTests.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,12 @@ public enum ShutdownChecks
108108
protected override void OnNewClientCreated(NetworkManager networkManager)
109109
{
110110
networkManager.NetworkConfig.EnableSceneManagement = m_UseSceneManagement;
111-
foreach (var prefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
112-
{
113-
networkManager.NetworkConfig.Prefabs.Add(prefab);
114-
}
115111
base.OnNewClientCreated(networkManager);
116112
}
117113

118114
/// <summary>
119115
/// Validate shutting down a second time does not cause an exception.
120-
/// </summary>
116+
/// </summary>
121117
[UnityTest]
122118
public IEnumerator ValidateShutdown([Values] ShutdownChecks shutdownCheck)
123119
{
@@ -132,7 +128,7 @@ public IEnumerator ValidateShutdown([Values] ShutdownChecks shutdownCheck)
132128
}
133129
else
134130
{
135-
// For this test (simplify the complexity) with a late joining client, just remove the
131+
// For this test (simplify the complexity) with a late joining client, just remove the
136132
// in-scene placed NetworkObject prior to the client connecting
137133
// (We are testing the shutdown sequence)
138134
var spawnedObjects = m_ServerNetworkManager.SpawnManager.SpawnedObjectsList.ToList();

testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkObjectSceneMigrationTests.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,6 @@ protected override void OnServerAndClientsCreated()
5959
base.OnServerAndClientsCreated();
6060
}
6161

62-
protected override void OnNewClientCreated(NetworkManager networkManager)
63-
{
64-
foreach (var networkPrfab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
65-
{
66-
if (networkPrfab.Prefab == null)
67-
{
68-
continue;
69-
}
70-
networkManager.NetworkConfig.Prefabs.Add(networkPrfab);
71-
}
72-
base.OnNewClientCreated(networkManager);
73-
}
74-
7562
private bool DidClientsSpawnInstance(NetworkObject serverObject, bool checkDestroyWithScene = false)
7663
{
7764
foreach (var networkManager in m_ClientNetworkManagers)

testproject/Assets/Tests/Runtime/ObjectParenting/ParentDynamicUnderInScenePlaced.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@ protected override IEnumerator OnStartedServerAndClients()
5757
return base.OnStartedServerAndClients();
5858
}
5959

60-
protected override void OnNewClientCreated(NetworkManager networkManager)
61-
{
62-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
63-
{
64-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
65-
}
66-
base.OnNewClientCreated(networkManager);
67-
}
68-
6960
protected override void OnNewClientStarted(NetworkManager networkManager)
7061
{
7162
m_ServerNetworkManager.SceneManager.SetClientSynchronizationMode(LoadSceneMode.Additive);

0 commit comments

Comments
 (0)