Skip to content

Commit 747711d

Browse files
fix
This fixes some compatibility issues with the initial total number of clients count being always +1 as opposed to just checking for the scenario where an integration test is connecting to a CMB server and has the `NetcodeIntegrationTest.NumberOfClients` set to zero (which in this case we have to create at least 1 client). This also updates the `m_NumberOfClients` when this scenario is detected. This also fixes some issues with allowing the `NetcodeIntegrationTest `to still create and assign `m_ServerNetworkManager`. The fix replaces all pertinent areas within `NetcodeIntegrationTest` that was directly using `m_ServerNetworkManager` with the returned value of `NetcodeIntegrationTest.GetAuthorityNetworkManager`.
1 parent 8dc06bf commit 747711d

File tree

3 files changed

+82
-39
lines changed

3 files changed

+82
-39
lines changed

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

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public static void DeregisterNetworkObject(ulong localClientId, ulong networkObj
9797
}
9898

9999
/// <summary>
100-
/// Total number of clients that should be connected at any point during a test
100+
/// Total number of clients that should be connected at any point during a test.
101101
/// </summary>
102102
protected int TotalClients => m_UseHost ? m_NumberOfClients + 1 : m_NumberOfClients;
103103

@@ -107,15 +107,21 @@ public static void DeregisterNetworkObject(ulong localClientId, ulong networkObj
107107
/// Specifies the number of client instances to be created for the integration test.
108108
/// </summary>
109109
/// <remarks>
110-
/// When running with a hosted CMB Service, NumberOfClients + 1 clients are created.
111-
/// This holds assumptions throughout the test suite that when running with a host, there is an extra client.
112-
/// For example, see the calculation for <see cref="TotalClients"/>.
110+
/// Client-Server network topology:<br />
111+
/// When running as a host the total number of clients will be NumberOfClients + 1.<br />
112+
/// See the calculation for <see cref="TotalClients"/>.
113+
/// Distributed Authority network topology:<br />
114+
/// When connecting to a CMB server, if the <see cref="NumberOfClients"/> == 0 then a session owner client will
115+
/// be automatically added in order to start the session and the private internal m_NumberOfClients value, which
116+
/// is initialized as <see cref="NumberOfClients"/>, will be incremented by 1 making <see cref="TotalClients"/> yield the
117+
/// same results as if we were running a Host where it will effectively be <see cref="NumberOfClients"/>
118+
/// + 1.
113119
/// </remarks>
114120
protected abstract int NumberOfClients { get; }
115121
private int m_NumberOfClients;
116122

117123
/// <summary>
118-
/// Set this to false to create the clients first.
124+
/// Set this to false to create the clients first.<br />
119125
/// Note: If you are using scene placed NetworkObjects or doing any form of scene testing and
120126
/// get prefab hash id "soft synchronization" errors, then set this to false and run your test
121127
/// again. This is a work-around until we can resolve some issues with NetworkManagerOwner and
@@ -513,7 +519,13 @@ protected virtual void OnServerAndClientsCreated()
513519
/// </summary>
514520
protected void CreateServerAndClients()
515521
{
516-
CreateServerAndClients(NumberOfClients);
522+
// If we are connecting to a CMB server and we have a zero client count,
523+
// then we must make m_NumberOfClients = 1 for the session owner.
524+
if (UseCMBService() && NumberOfClients == 0 && m_NumberOfClients == 0)
525+
{
526+
m_NumberOfClients = 1;
527+
}
528+
CreateServerAndClients(m_NumberOfClients);
517529
}
518530

519531
private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetworkManager)
@@ -546,7 +558,7 @@ private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetw
546558
protected virtual void OnNewClientCreated(NetworkManager networkManager)
547559
{
548560
// Ensure any late joining client has all NetworkPrefabs required to connect.
549-
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs)
561+
foreach (var networkPrefab in GetAuthorityNetworkManager().NetworkConfig.Prefabs.Prefabs)
550562
{
551563
if (!networkManager.NetworkConfig.Prefabs.Contains(networkPrefab.Prefab))
552564
{
@@ -761,7 +773,7 @@ protected void StopOneClientWithTimeTravel(NetworkManager networkManager, bool d
761773

762774
protected void SetTimeTravelSimulatedLatency(float latencySeconds)
763775
{
764-
((MockTransport)m_ServerNetworkManager.NetworkConfig.NetworkTransport).SimulatedLatencySeconds = latencySeconds;
776+
((MockTransport)GetAuthorityNetworkManager().NetworkConfig.NetworkTransport).SimulatedLatencySeconds = latencySeconds;
765777
foreach (var client in m_ClientNetworkManagers)
766778
{
767779
((MockTransport)client.NetworkConfig.NetworkTransport).SimulatedLatencySeconds = latencySeconds;
@@ -770,7 +782,7 @@ protected void SetTimeTravelSimulatedLatency(float latencySeconds)
770782

771783
protected void SetTimeTravelSimulatedDropRate(float dropRatePercent)
772784
{
773-
((MockTransport)m_ServerNetworkManager.NetworkConfig.NetworkTransport).PacketDropRate = dropRatePercent;
785+
((MockTransport)GetAuthorityNetworkManager().NetworkConfig.NetworkTransport).PacketDropRate = dropRatePercent;
774786
foreach (var client in m_ClientNetworkManagers)
775787
{
776788
((MockTransport)client.NetworkConfig.NetworkTransport).PacketDropRate = dropRatePercent;
@@ -779,7 +791,7 @@ protected void SetTimeTravelSimulatedDropRate(float dropRatePercent)
779791

780792
protected void SetTimeTravelSimulatedLatencyJitter(float jitterSeconds)
781793
{
782-
((MockTransport)m_ServerNetworkManager.NetworkConfig.NetworkTransport).LatencyJitter = jitterSeconds;
794+
((MockTransport)GetAuthorityNetworkManager().NetworkConfig.NetworkTransport).LatencyJitter = jitterSeconds;
783795
foreach (var client in m_ClientNetworkManagers)
784796
{
785797
((MockTransport)client.NetworkConfig.NetworkTransport).LatencyJitter = jitterSeconds;
@@ -801,10 +813,23 @@ protected void CreateServerAndClients(int numberOfClients)
801813
m_TargetFrameRate = -1;
802814
}
803815

804-
// Add an extra session owner client when using the cmb service
805-
if (m_UseCmbService)
816+
// In the event this is invoked within a derived integration test and
817+
// the number of clients is 0, then we need to have at least 1 client
818+
// to be the session owner.
819+
if (UseCMBService() && numberOfClients == 0)
806820
{
807-
numberOfClients += 1;
821+
numberOfClients = 1;
822+
// If m_NumberOfCleints == 0, then we should increment it.
823+
if (m_NumberOfClients == 0)
824+
{
825+
m_NumberOfClients = 1;
826+
}
827+
else
828+
{
829+
// Otherwise, log a warning to the developer that they may be doing something bad.
830+
Debug.LogWarning($"[{nameof(CreateServerAndClients)}] Invoked with number of clients set to zero but m_NumberOfClients was {m_NumberOfClients}. " +
831+
$"Unless this was intended, this could cause issues with the {nameof(NetcodeIntegrationTest)}!");
832+
}
808833
}
809834

810835
// Create multiple NetworkManager instances
@@ -824,7 +849,7 @@ protected void CreateServerAndClients(int numberOfClients)
824849
}
825850
m_NetworkManagers = managers.ToArray();
826851

827-
s_DefaultWaitForTick = new WaitForSecondsRealtime(1.0f / m_ServerNetworkManager.NetworkConfig.TickRate);
852+
s_DefaultWaitForTick = new WaitForSecondsRealtime(1.0f / GetAuthorityNetworkManager().NetworkConfig.TickRate);
828853

829854
// Set the player prefab for the server and clients
830855
foreach (var manager in m_NetworkManagers)
@@ -943,7 +968,7 @@ protected void ClientNetworkManagerPostStartInit()
943968
if (m_UseHost)
944969
{
945970
#if UNITY_2023_1_OR_NEWER
946-
var clientSideServerPlayerClones = Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.None).Where((c) => c.IsPlayerObject && c.OwnerClientId == m_ServerNetworkManager.LocalClientId);
971+
var clientSideServerPlayerClones = Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.None).Where((c) => c.IsPlayerObject && c.OwnerClientId == NetworkManager.ServerClientId);
947972
#else
948973
var clientSideServerPlayerClones = Object.FindObjectsOfType<NetworkObject>().Where((c) => c.IsPlayerObject && c.OwnerClientId == m_ServerNetworkManager.LocalClientId);
949974
#endif
@@ -955,9 +980,9 @@ protected void ClientNetworkManagerPostStartInit()
955980
m_PlayerNetworkObjects.Add(playerNetworkObject.NetworkManager.LocalClientId, new Dictionary<ulong, NetworkObject>());
956981
}
957982

958-
if (!m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].ContainsKey(m_ServerNetworkManager.LocalClientId))
983+
if (!m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].ContainsKey(NetworkManager.ServerClientId))
959984
{
960-
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(m_ServerNetworkManager.LocalClientId, playerNetworkObject);
985+
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(NetworkManager.ServerClientId, playerNetworkObject);
961986
}
962987
}
963988
}
@@ -1021,7 +1046,7 @@ protected IEnumerator StartServerAndClients()
10211046

10221047
AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}");
10231048

1024-
if (m_UseHost || m_ServerNetworkManager.IsHost)
1049+
if (m_UseHost || authorityManager.IsHost)
10251050
{
10261051
#if UNITY_2023_1_OR_NEWER
10271052
// Add the server player instance to all m_ClientSidePlayerNetworkObjects entries
@@ -1039,7 +1064,7 @@ protected IEnumerator StartServerAndClients()
10391064

10401065
if (!m_UseCmbService)
10411066
{
1042-
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(m_ServerNetworkManager.LocalClientId, playerNetworkObject);
1067+
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(authorityManager.LocalClientId, playerNetworkObject);
10431068
}
10441069
}
10451070
}
@@ -1111,7 +1136,7 @@ protected void StartServerAndClientsWithTimeTravel()
11111136

11121137
AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!");
11131138

1114-
if (m_UseHost || m_ServerNetworkManager.IsHost)
1139+
if (m_UseHost || authorityManager.IsHost)
11151140
{
11161141
#if UNITY_2023_1_OR_NEWER
11171142
// Add the server player instance to all m_ClientSidePlayerNetworkObjects entries
@@ -1129,7 +1154,7 @@ protected void StartServerAndClientsWithTimeTravel()
11291154

11301155
if (!m_UseCmbService)
11311156
{
1132-
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(m_ServerNetworkManager.LocalClientId, playerNetworkObject);
1157+
m_PlayerNetworkObjects[playerNetworkObject.NetworkManager.LocalClientId].Add(authorityManager.LocalClientId, playerNetworkObject);
11331158
}
11341159
}
11351160
}
@@ -1449,10 +1474,9 @@ protected void DestroySceneNetworkObjects()
14491474
/// </summary>
14501475
protected void EnableMessageLogging()
14511476
{
1452-
m_ServerNetworkManager.ConnectionManager.MessageManager.Hook(new DebugNetworkHooks());
1453-
foreach (var client in m_ClientNetworkManagers)
1477+
foreach (var networkManager in m_NetworkManagers)
14541478
{
1455-
client.ConnectionManager.MessageManager.Hook(new DebugNetworkHooks());
1479+
networkManager.ConnectionManager.MessageManager.Hook(new DebugNetworkHooks());
14561480
}
14571481
}
14581482

@@ -1632,10 +1656,11 @@ private bool CheckClientsConnected(NetworkManager[] clientsToCheck)
16321656
protected bool WaitForClientsConnectedOrTimeOutWithTimeTravel(NetworkManager[] clientsToCheck)
16331657
{
16341658
var remoteClientCount = clientsToCheck.Length;
1635-
var serverClientCount = m_ServerNetworkManager.IsHost ? remoteClientCount + 1 : remoteClientCount;
1659+
var authorityNetworkManager = GetAuthorityNetworkManager();
1660+
var serverClientCount = authorityNetworkManager.IsHost ? remoteClientCount + 1 : remoteClientCount;
16361661

16371662
return WaitForConditionOrTimeOutWithTimeTravel(() => clientsToCheck.Where((c) => c.IsConnectedClient).Count() == remoteClientCount &&
1638-
m_ServerNetworkManager.ConnectedClients.Count == serverClientCount);
1663+
authorityNetworkManager.ConnectedClients.Count == serverClientCount);
16391664
}
16401665

16411666
/// <summary>
@@ -1746,9 +1771,10 @@ protected GameObject CreateNetworkObjectPrefab(string baseName)
17461771
{
17471772
var prefabCreateAssertError = $"You can only invoke this method during {nameof(OnServerAndClientsCreated)} " +
17481773
$"but before {nameof(OnStartedServerAndClients)}!";
1749-
Assert.IsNotNull(m_ServerNetworkManager, prefabCreateAssertError);
1750-
Assert.IsFalse(m_ServerNetworkManager.IsListening, prefabCreateAssertError);
1751-
var prefabObject = NetcodeIntegrationTestHelpers.CreateNetworkObjectPrefab(baseName, m_ServerNetworkManager, m_ClientNetworkManagers);
1774+
var authorityNetworkManager = GetAuthorityNetworkManager();
1775+
Assert.IsNotNull(authorityNetworkManager, prefabCreateAssertError);
1776+
Assert.IsFalse(authorityNetworkManager.IsListening, prefabCreateAssertError);
1777+
var prefabObject = NetcodeIntegrationTestHelpers.CreateNetworkObjectPrefab(baseName, authorityNetworkManager, m_ClientNetworkManagers);
17521778
// DANGO-TODO: Ownership flags could require us to change this
17531779
// For testing purposes, we default to true for the distribute ownership property when in a distirbuted authority network topology.
17541780
prefabObject.GetComponent<NetworkObject>().Ownership |= NetworkObject.OwnershipStatus.Distributable;

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,16 +265,18 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
265265
{
266266
s_NetworkManagerInstances = new List<NetworkManager>();
267267
server = null;
268-
if (serverFirst)
268+
// Only if we are not connecting to a CMB server
269+
if (serverFirst && !useCmbService)
269270
{
270-
server = CreateServer(useMockTransport || useCmbService);
271+
server = CreateServer(useMockTransport);
271272
}
272273

273274
CreateNewClients(clientCount, out clients, useMockTransport, useCmbService);
274275

275-
if (!serverFirst)
276+
// Only if we are not connecting to a CMB server
277+
if (!serverFirst && !useCmbService)
276278
{
277-
server = CreateServer(useMockTransport || useCmbService);
279+
server = CreateServer(useMockTransport);
278280
}
279281

280282
s_OriginalTargetFrameRate = Application.targetFrameRate;
@@ -627,25 +629,41 @@ internal static GameObject CreateNetworkObject(string baseName, NetworkManager o
627629
return gameObject;
628630
}
629631

630-
public static GameObject CreateNetworkObjectPrefab(string baseName, NetworkManager server, params NetworkManager[] clients)
632+
/// <summary>
633+
/// This will create and register a <see cref="NetworkPrefab"/> instance for all <see cref="NetworkManager"/> instances.<br />
634+
/// *** Invoke this method before starting any of the <see cref="NetworkManager"/> instances ***.
635+
/// </summary>
636+
/// <remarks>
637+
/// When using a <see cref="NetworkTopologyTypes.DistributedAuthority"/> network topology, the authority <see cref="NetworkManager"/>
638+
/// can be within the clients array of <see cref="NetworkManager"/> instances.
639+
/// </remarks>
640+
/// <param name="baseName">The base name of the network prefab. Keep it short as additional information will be added to this name.</param>
641+
/// <param name="authorityNetworkManager">The authority <see cref="NetworkManager"/> (i.e. server, host, or session owner)</param>
642+
/// <param name="clients">The clients that should also have this <see cref="NetworkPrefab"/> instance added to their network prefab list.</param>
643+
/// <returns>The prefab's root <see cref="GameObject"/></returns>
644+
public static GameObject CreateNetworkObjectPrefab(string baseName, NetworkManager authorityNetworkManager, params NetworkManager[] clients)
631645
{
632646
void AddNetworkPrefab(NetworkConfig config, NetworkPrefab prefab)
633647
{
634648
config.Prefabs.Add(prefab);
635649
}
636650

637651
var prefabCreateAssertError = $"You can only invoke this method before starting the network manager(s)!";
638-
Assert.IsNotNull(server, prefabCreateAssertError);
639-
Assert.IsFalse(server.IsListening, prefabCreateAssertError);
652+
Assert.IsNotNull(authorityNetworkManager, prefabCreateAssertError);
653+
Assert.IsFalse(authorityNetworkManager.IsListening, prefabCreateAssertError);
640654

641-
var gameObject = CreateNetworkObject(baseName, server);
655+
var gameObject = CreateNetworkObject(baseName, authorityNetworkManager);
642656
var networkPrefab = new NetworkPrefab() { Prefab = gameObject };
643657

644658
// We could refactor this test framework to share a NetworkPrefabList instance, but at this point it's
645659
// probably more trouble than it's worth to verify these lists stay in sync across all tests...
646-
AddNetworkPrefab(server.NetworkConfig, networkPrefab);
660+
AddNetworkPrefab(authorityNetworkManager.NetworkConfig, networkPrefab);
647661
foreach (var clientNetworkManager in clients)
648662
{
663+
if (clientNetworkManager == authorityNetworkManager)
664+
{
665+
continue;
666+
}
649667
AddNetworkPrefab(clientNetworkManager.NetworkConfig, networkPrefab);
650668
}
651669
return gameObject;

pvpExceptions.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@
173173
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: uint GetNextGlobalIdHashValue(): undocumented",
174174
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: IsNetcodeIntegrationTestRunning: undocumented",
175175
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: void RegisterNetcodeIntegrationTest(bool): undocumented",
176-
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: GameObject CreateNetworkObjectPrefab(string, NetworkManager, params NetworkManager[]): undocumented",
177176
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: void MarkAsSceneObjectRoot(GameObject, NetworkManager, NetworkManager[]): undocumented",
178177
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: IEnumerator WaitForClientConnected(NetworkManager, ResultWrapper<bool>, float): missing <returns>",
179178
"Unity.Netcode.TestHelpers.Runtime.NetcodeIntegrationTestHelpers: IEnumerator WaitForClientsConnected(NetworkManager[], ResultWrapper<bool>, float): missing <returns>",

0 commit comments

Comments
 (0)