Skip to content

Commit 253fc9f

Browse files
Merge branch 'develop' into codeowners-correction-1.x
2 parents b505571 + b0863ca commit 253fc9f

18 files changed

+225
-103
lines changed

.yamato/_run-all.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,11 @@ run_all_webgl_builds:
102102
dependencies:
103103
{% for project in projects.default -%}
104104
{% for platform in test_platforms.desktop -%}
105+
{% if platform.name != "mac" -%} # There is an error about "Light baking could not be started because no valid OpenCL device could be found". Tracked in MTT-11726
105106
{% for editor in validation_editors.all -%}
106107
- .yamato/webgl-build.yml#webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}
107108
{% endfor -%}
109+
{% endif -%}
108110
{% endfor -%}
109111
{% endfor -%}
110112

@@ -115,9 +117,11 @@ run_all_webgl_builds_trunk:
115117
dependencies:
116118
{% for project in projects.default -%}
117119
{% for platform in test_platforms.desktop -%}
120+
{% if platform.name != "mac" -%} # There is an error about "Light baking could not be started because no valid OpenCL device could be found". Tracked in MTT-11726
118121
{% for editor in validation_editors.default -%}
119122
- .yamato/webgl-build.yml#webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}
120123
{% endfor -%}
124+
{% endif -%}
121125
{% endfor -%}
122126
{% endfor -%}
123127

@@ -127,7 +131,9 @@ run_all_webgl_builds_2021:
127131
dependencies:
128132
{% for project in projects.default -%}
129133
{% for platform in test_platforms.desktop -%}
134+
{% if platform.name != "mac" -%} # There is an error about "Light baking could not be started because no valid OpenCL device could be found". Tracked in MTT-11726
130135
- .yamato/webgl-build.yml#webgl_build_{{ project.name }}_{{ platform.name }}_2021.3
136+
{% endif -%}
131137
{% endfor -%}
132138
{% endfor -%}
133139

.yamato/webgl-build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
{% for project in projects.default -%}
2727
{% for platform in test_platforms.desktop -%}
28+
{% if platform.name != "mac" -%} # There is an error about "Light baking could not be started because no valid OpenCL device could be found". Tracked in MTT-11726
2829
{% for editor in validation_editors.all -%}
2930
webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}:
3031
name: WebGl Build - {{ project.name }} [{{ platform.name }}, {{ editor }}, il2cpp]
@@ -37,7 +38,7 @@ webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}:
3738
{% endif %}
3839
commands:
3940
- unity-downloader-cli --fast --wait -u {{ editor }} -c Editor -c webgl -c il2cpp {% if platform.name == "mac" %} --arch arm64 {% endif %} # For macOS we use ARM64 models. Downloading the editor with additional webgl and il2cpp components
40-
41+
4142
# The following step builds the player with defined options such as:
4243
# Suite parameter if defined since it's a mandatory field to define which test suite should be used, but it doesn't matter in this case since we won't run any tests (--suite)
4344
# Editor is run in batchmode, which means that Unity runs command line arguments without the need for human interaction. It also suppresses pop-up windows that require human interaction (such as the Save Scene window). We should always run Unity in batch mode when using command line arguments, because it allows automation to run without interruption. (--extra-editor-arg=-batchmode)
@@ -51,5 +52,6 @@ webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}:
5152
- "artifacts/**/*"
5253
- "build/players/**/*"
5354
{% endfor -%}
55+
{% endif -%}
5456
{% endfor -%}
5557
{% endfor -%}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,14 @@ private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetw
524524
/// <param name="networkManager">The NetworkManager instance of the client.</param>
525525
protected virtual void OnNewClientCreated(NetworkManager networkManager)
526526
{
527+
// Ensure any late joining client has all NetworkPrefabs required to connect.
528+
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
529+
{
530+
if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab))
531+
{
532+
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
533+
}
534+
}
527535
}
528536

529537
/// <summary>

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,7 @@ protected override void OnNewClientCreated(NetworkManager networkManager)
256256
{
257257
AddPrefabsToClient(networkManager);
258258
}
259-
260-
base.OnNewClientCreated(networkManager);
259+
// Don't call base as this will synchronize the prefabs
261260
}
262261

263262
private void SpawnClients(bool clearTestDeferredMessageManagerCallFlags = true)

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ protected override IEnumerator OnSetup()
8888
return base.OnSetup();
8989
}
9090

91-
protected override void OnNewClientCreated(NetworkManager networkManager)
92-
{
93-
networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs;
94-
base.OnNewClientCreated(networkManager);
95-
}
96-
9791
/// <summary>
9892
/// This validates that pre spawn can be used to instantiate and assign a NetworkVariable (or other prespawn tasks)
9993
/// which can be useful for assigning a NetworkVariable value on the server side when the NetworkVariable has owner write permissions.

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,10 @@ private bool CheckClientsSideObserverTestObj()
6262
}
6363

6464
/// <summary>
65-
/// Assures the <see cref="ObserverSpawnTests"/> late joining client has all
66-
/// NetworkPrefabs required to connect.
65+
/// Set up late joining client
6766
/// </summary>
6867
protected override void OnNewClientCreated(NetworkManager networkManager)
6968
{
70-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
71-
{
72-
if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab))
73-
{
74-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
75-
}
76-
}
7769
networkManager.NetworkConfig.EnableSceneManagement = m_ServerNetworkManager.NetworkConfig.EnableSceneManagement;
7870
base.OnNewClientCreated(networkManager);
7971
}

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

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

7777
protected override void OnNewClientCreated(NetworkManager networkManager)
7878
{
79+
// Setup late joining client prefabs first
80+
base.OnNewClientCreated(networkManager);
81+
7982
networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
8083
networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety;
81-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
82-
{
83-
// To simulate a failure, we exclude the m_InValidNetworkPrefab from the connecting
84-
// client's side.
85-
if (networkPrefab.Prefab.name != m_InValidNetworkPrefab.name)
86-
{
87-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
88-
}
89-
}
84+
9085
// Disable forcing the same prefabs to avoid failed connections
9186
networkManager.NetworkConfig.ForceSamePrefabs = false;
9287
networkManager.LogLevel = m_CurrentLogLevel;
93-
base.OnNewClientCreated(networkManager);
88+
// To simulate a failure, exclude the m_InValidNetworkPrefab from the connecting client's side.
89+
networkManager.NetworkConfig.Prefabs.Remove(m_InValidNetworkPrefab);
9490
}
9591

9692
[UnityTest]

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ protected override IEnumerator OnServerAndClientsConnected()
339339
/// </summary>
340340
protected override void OnNewClientCreated(NetworkManager networkManager)
341341
{
342-
networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs;
343342
networkManager.NetworkConfig.TickRate = GetTickRate();
344343
if (m_EnableVerboseDebug)
345344
{

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,6 @@ protected override void OnServerAndClientsCreated()
4646
base.OnServerAndClientsCreated();
4747
}
4848

49-
/// <summary>
50-
/// Clients created during a test need to have their prefabs list updated to
51-
/// match the server's prefab list.
52-
/// </summary>
53-
protected override void OnNewClientCreated(NetworkManager networkManager)
54-
{
55-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
56-
{
57-
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
58-
}
59-
60-
base.OnNewClientCreated(networkManager);
61-
}
62-
6349
private bool ClientIsOwner()
6450
{
6551
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 State = 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 (State != 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+
State = 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+
State = 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.State == 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+
}

0 commit comments

Comments
 (0)