diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
index b5a042c843..d2d1e34fea 100644
--- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs
@@ -1123,7 +1123,7 @@ internal void Initialize(bool server)
UpdateTopology();
//DANGOEXP TODO: Remove this before finalizing the experimental release
- NetworkConfig.AutoSpawnPlayerPrefabClientSide = DistributedAuthorityMode;
+ //NetworkConfig.AutoSpawnPlayerPrefabClientSide = DistributedAuthorityMode;
// Make sure the ServerShutdownState is reset when initializing
if (server)
diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs
index a048cea2ca..75ce48aa1c 100644
--- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs
+++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs
@@ -187,7 +187,9 @@ public virtual void SetDirty(bool isDirty)
internal bool CanSend()
{
- var timeSinceLastUpdate = m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime - LastUpdateSent;
+ // When connected to a service or not the server, always use the synchronized server time as opposed to the local time
+ var time = m_InternalNetworkManager.CMBServiceConnection || !m_InternalNetworkManager.IsServer ? m_NetworkBehaviour.NetworkManager.ServerTime.Time : m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
+ var timeSinceLastUpdate = time - LastUpdateSent;
return
(
UpdateTraits.MaxSecondsBetweenUpdates > 0 &&
@@ -201,7 +203,8 @@ internal bool CanSend()
internal void UpdateLastSentTime()
{
- LastUpdateSent = m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
+ // When connected to a service or not the server, always use the synchronized server time as opposed to the local time
+ LastUpdateSent = m_InternalNetworkManager.CMBServiceConnection || !m_InternalNetworkManager.IsServer ? m_NetworkBehaviour.NetworkManager.ServerTime.Time : m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
}
internal static bool IgnoreInitializeWarning;
diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
index 975697862b..4a7ef4a19c 100644
--- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
+++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs
@@ -2011,7 +2011,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)
// NetworkSceneManager does not synchronize scenes that are not loaded by NetworkSceneManager
// unless the scene in question is the currently active scene.
- if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene))
+ if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene) &&
+ (!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
@@ -2025,7 +2026,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)
// If we are the base scene, then we set the root scene index;
if (activeScene == scene)
{
- if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
+ if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode) &&
+ (!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
@@ -2042,7 +2044,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)
sceneEventData.SceneHandle = scene.handle;
}
}
- else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
+ else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive) &&
+ (!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
diff --git a/com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs b/com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs
index 216569355c..4a0654aefe 100644
--- a/com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs
+++ b/com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs
@@ -128,6 +128,27 @@ public enum HostOrServer
protected NetworkManager m_ServerNetworkManager;
protected NetworkManager[] m_ClientNetworkManagers;
+ ///
+ /// When using a client-server network topology, it will always return the m_ServerNetworkManager.
+ /// When using a distributed authority network topology:
+ /// - If running a DAHost it will return m_ServerNetworkManager
+ /// - If using a comb-server connection, it will return the client that is the currently assigned session owner.
+ ///
+ ///
+ protected NetworkManager GetSessionOwner()
+ {
+ if (!UseCMBService())
+ {
+ return m_ServerNetworkManager;
+ }
+ if (m_ClientNetworkManagers.Length > 0)
+ {
+ var sessionOwnerId = m_ClientNetworkManagers[0].CurrentSessionOwner;
+ return m_ClientNetworkManagers.Where((c) => c.LocalClientId == sessionOwnerId).FirstOrDefault();
+ }
+ return null;
+ }
+
///
/// Contains each client relative set of player NetworkObject instances
/// [Client Relative set of player instances][The player instance ClientId][The player instance's NetworkObject]
@@ -141,9 +162,10 @@ public enum HostOrServer
protected bool m_DistributedAuthority;
protected NetworkTopologyTypes m_NetworkTopologyType = NetworkTopologyTypes.ClientServer;
+ public static bool UseCMBServiceForDATests;
protected virtual bool UseCMBService()
{
- return false;
+ return UseCMBServiceForDATests ? m_DistributedAuthority : false;
}
protected virtual NetworkTopologyTypes OnGetNetworkTopologyType()
@@ -531,7 +553,7 @@ protected IEnumerator CreateAndStartNewClient()
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for the new client to be connected!\n {m_InternalErrorLog}");
ClientNetworkManagerPostStart(networkManager);
- if (networkManager.DistributedAuthorityMode)
+ if (networkManager.DistributedAuthorityMode && networkManager.NetworkConfig.AutoSpawnPlayerPrefabClientSide)
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(networkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!");
@@ -546,19 +568,22 @@ private bool AllPlayerObjectClonesSpawned(NetworkManager joinedClient)
m_InternalErrorLog.Clear();
// Continue to populate the PlayerObjects list until all player object (local and clone) are found
ClientNetworkManagerPostStart(joinedClient);
-
- var playerObjectRelative = m_ServerNetworkManager.SpawnManager.PlayerObjects.Where((c) => c.OwnerClientId == joinedClient.LocalClientId).FirstOrDefault();
- if (playerObjectRelative == null)
+ var playerObjectRelative = (NetworkObject)null;
+ if (!UseCMBService())
{
- m_InternalErrorLog.Append($"[AllPlayerObjectClonesSpawned][Server-Side] Joining Client-{joinedClient.LocalClientId} was not populated in the {nameof(NetworkSpawnManager.PlayerObjects)} list!");
- return false;
- }
- else
- {
- // Go ahead and create an entry for this new client
- if (!m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(joinedClient.LocalClientId))
+ playerObjectRelative = m_ServerNetworkManager.SpawnManager.PlayerObjects.Where((c) => c.OwnerClientId == joinedClient.LocalClientId).FirstOrDefault();
+ if (playerObjectRelative == null)
+ {
+ m_InternalErrorLog.Append($"[AllPlayerObjectClonesSpawned][Server-Side] Joining Client-{joinedClient.LocalClientId} was not populated in the {nameof(NetworkSpawnManager.PlayerObjects)} list!");
+ return false;
+ }
+ else
{
- m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].Add(joinedClient.LocalClientId, playerObjectRelative);
+ // Go ahead and create an entry for this new client
+ if (!m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(joinedClient.LocalClientId))
+ {
+ m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].Add(joinedClient.LocalClientId, playerObjectRelative);
+ }
}
}
@@ -770,6 +795,11 @@ protected virtual void OnTimeTravelServerAndClientsConnected()
private void ClientNetworkManagerPostStart(NetworkManager networkManager)
{
+ if (m_DistributedAuthority && !networkManager.NetworkConfig.AutoSpawnPlayerPrefabClientSide)
+ {
+ return;
+ }
+
networkManager.name = $"NetworkManager - Client - {networkManager.LocalClientId}";
Assert.NotNull(networkManager.LocalClient.PlayerObject, $"{nameof(StartServerAndClients)} detected that client {networkManager.LocalClientId} does not have an assigned player NetworkObject!");
@@ -818,14 +848,19 @@ private void ClientNetworkManagerPostStart(NetworkManager networkManager)
protected void ClientNetworkManagerPostStartInit()
{
+
// Creates a dictionary for all player instances client and server relative
// This provides a simpler way to get a specific player instance relative to a client instance
foreach (var networkManager in m_ClientNetworkManagers)
{
+ if (networkManager.DistributedAuthorityMode && !networkManager.AutoSpawnPlayerPrefabClientSide)
+ {
+ continue;
+ }
ClientNetworkManagerPostStart(networkManager);
}
- if (m_UseHost)
+ if (m_UseHost && !UseCMBService())
{
#if UNITY_2023_1_OR_NEWER
var clientSideServerPlayerClones = Object.FindObjectsByType(FindObjectsSortMode.None).Where((c) => c.IsPlayerObject && c.OwnerClientId == m_ServerNetworkManager.LocalClientId);
@@ -901,7 +936,7 @@ protected IEnumerator StartServerAndClients()
AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}");
- if (m_UseHost || m_ServerNetworkManager.IsHost)
+ if (!UseCMBService() && (m_UseHost || m_ServerNetworkManager.IsHost))
{
#if UNITY_2023_1_OR_NEWER
// Add the server player instance to all m_ClientSidePlayerNetworkObjects entries
@@ -926,13 +961,13 @@ protected IEnumerator StartServerAndClients()
//AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn all player objects!");
foreach (var networkManager in m_ClientNetworkManagers)
{
- if (networkManager.DistributedAuthorityMode)
+ if (networkManager.DistributedAuthorityMode && networkManager.AutoSpawnPlayerPrefabClientSide)
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(networkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!\n {m_InternalErrorLog}");
}
}
- if (m_ServerNetworkManager != null)
+ if (m_ServerNetworkManager != null && !UseCMBService())
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(m_ServerNetworkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{m_ServerNetworkManager.LocalClientId}'s player object!\n {m_InternalErrorLog}");
@@ -1459,7 +1494,7 @@ private bool CheckClientsConnected(NetworkManager[] clientsToCheck)
{
m_InternalErrorLog.Clear();
var allClientsConnected = true;
-
+ var actualConnected = 0;
for (int i = 0; i < clientsToCheck.Length; i++)
{
if (!clientsToCheck[i].IsConnectedClient)
@@ -1467,14 +1502,21 @@ private bool CheckClientsConnected(NetworkManager[] clientsToCheck)
allClientsConnected = false;
m_InternalErrorLog.AppendLine($"[Client-{i + 1}] Client is not connected!");
}
+ else
+ {
+ actualConnected++;
+ }
}
- var expectedCount = m_ServerNetworkManager.IsHost ? clientsToCheck.Length + 1 : clientsToCheck.Length;
- var currentCount = m_ServerNetworkManager.ConnectedClients.Count;
- if (currentCount != expectedCount)
+ var expectedCount = m_ServerNetworkManager.IsHost && !UseCMBService() && !m_ServerNetworkManager.IsConnectedClient ? clientsToCheck.Length + 1 : clientsToCheck.Length;
+
+
+ if (expectedCount != actualConnected)
{
+ var currentCount = GetSessionOwner().ConnectedClients.Count;
+ var logErrorHeader = !UseCMBService() ? "[Server-Side]" : "[SessionOwner-Side]";
allClientsConnected = false;
- m_InternalErrorLog.AppendLine($"[Server-Side] Expected {expectedCount} clients to connect but only {currentCount} connected!");
+ m_InternalErrorLog.AppendLine($"{logErrorHeader} Expected {expectedCount} clients to connect but only {actualConnected} connected with a total of {currentCount} connected clients!");
}
return allClientsConnected;
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs
index faba405079..f2c9390212 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Text;
using NUnit.Framework;
using Unity.Netcode.TestHelpers.Runtime;
using UnityEngine;
@@ -9,14 +10,16 @@
namespace Unity.Netcode.RuntimeTests
{
+ [TestFixture(HostOrServer.DAHost)]
internal class DeferredDespawningTests : IntegrationTestWithApproximation
{
private const int k_DaisyChainedCount = 5;
protected override int NumberOfClients => 2;
private List m_DaisyChainedDespawnObjects = new List();
private List m_HasReachedEnd = new List();
+ private NetworkManager m_SessionOwner;
- public DeferredDespawningTests() : base(HostOrServer.DAHost)
+ public DeferredDespawningTests(HostOrServer hostOrServer) : base(hostOrServer)
{
}
@@ -33,6 +36,7 @@ protected override void OnServerAndClientsCreated()
daisyChainPrevious.PrefabToSpawnWhenDespawned = daisyChainBehaviour.gameObject;
}
m_DaisyChainedDespawnObjects.Add(daisyChainNode);
+ daisyChainNode.SetActive(false);
daisyChainPrevious = daisyChainBehaviour;
}
@@ -40,22 +44,25 @@ protected override void OnServerAndClientsCreated()
base.OnServerAndClientsCreated();
}
-
-
[UnityTest]
public IEnumerator DeferredDespawning()
{
- DeferredDespawnDaisyChained.EnableVerbose = m_EnableVerboseDebug;
- var rootInstance = SpawnObject(m_DaisyChainedDespawnObjects[0], m_ServerNetworkManager);
+ DeferredDespawnDaisyChained.TestFailed.Clear();
+ m_SessionOwner = GetSessionOwner();
+ foreach (var daisyChaingedObject in m_DaisyChainedDespawnObjects)
+ {
+ daisyChaingedObject.SetActive(true);
+ }
+ var rootInstance = SpawnObject(m_DaisyChainedDespawnObjects[0], m_SessionOwner);
DeferredDespawnDaisyChained.ReachedLastChainInstance = ReachedLastChainObject;
- var timeoutHelper = new TimeoutHelper(300);
+ var timeoutHelper = new TimeoutHelper(30);
yield return WaitForConditionOrTimeOut(HaveAllClientsReachedEndOfChain, timeoutHelper);
- AssertOnTimeout($"Timed out waiting for all children to reach the end of their chained deferred despawns!", timeoutHelper);
+ AssertOnTimeout($"Timed out waiting for all children to reach the end of their chained deferred despawns! {DeferredDespawnDaisyChained.TestFailed.ToString()}", timeoutHelper);
}
private bool HaveAllClientsReachedEndOfChain()
{
- if (!m_HasReachedEnd.Contains(m_ServerNetworkManager.LocalClientId))
+ if (!m_HasReachedEnd.Contains(m_SessionOwner.LocalClientId))
{
return false;
}
@@ -111,9 +118,11 @@ private void PingInstance()
private DeferredDespawnDaisyChained m_NextNodeSpawned = null;
+ public static StringBuilder TestFailed = new StringBuilder();
+
private void FailTest(string msg)
{
- Assert.Fail($"[{nameof(DeferredDespawnDaisyChained)}][Client-{NetworkManager.LocalClientId}] {msg}");
+ TestFailed.AppendLine($"[{nameof(DeferredDespawnDaisyChained)}][Client-{NetworkManager.LocalClientId}] {msg}");
}
public override void OnNetworkSpawn()
@@ -134,6 +143,7 @@ public override void OnNetworkSpawn()
if (!HasAuthority)
{
m_ValidateDirtyNetworkVarUpdate.OnValueChanged += OnValidateDirtyChanged;
+ m_ValidateDirtyNetworkVarUpdate.Value.TryGet(out m_NextNodeSpawned, NetworkManager);
}
if (HasAuthority && IsRoot)
@@ -146,6 +156,7 @@ public override void OnNetworkSpawn()
private void OnValidateDirtyChanged(NetworkBehaviourReference previous, NetworkBehaviourReference current)
{
+ Log($"[OnValidateDirtyChanged] Getting NetworkBehaviour component....");
if (!HasAuthority)
{
if (!current.TryGet(out m_NextNodeSpawned, NetworkManager))
@@ -157,6 +168,11 @@ private void OnValidateDirtyChanged(NetworkBehaviourReference previous, NetworkB
{
FailTest($"[{nameof(NetworkManager)}][{nameof(NetworkBehaviourReference.TryGet)}] The {nameof(NetworkManager)} of {nameof(m_NextNodeSpawned)} does not match the local relative {nameof(NetworkManager)} instance!");
}
+
+ if (m_NextNodeSpawned != null)
+ {
+ Log($"[OnValidateDirtyChanged] m_NextNodeSpawned set -- {m_NextNodeSpawned.name}!");
+ }
}
}
@@ -164,8 +180,19 @@ public override void OnNetworkDespawn()
{
if (!HasAuthority && !NetworkManager.ShutdownInProgress)
{
+ Log($"[OnNetworkDespawn] despawning... ");
if (PrefabToSpawnWhenDespawned != null)
{
+ if (m_NextNodeSpawned == null)
+ {
+ Log($"[OnNetworkDespawn] No m_NextNodeSpawned set!!!");
+ if (!m_ValidateDirtyNetworkVarUpdate.Value.TryGet(out m_NextNodeSpawned, NetworkManager))
+ {
+ FailTest($"[{nameof(OnValidateDirtyChanged)}][{nameof(NetworkBehaviourReference)}] Failed to get the {nameof(DeferredDespawnDaisyChained)} behaviour from the {nameof(NetworkBehaviourReference)}!");
+ return;
+ }
+ }
+ Log($"[OnNetworkDespawn] Pinging {m_NextNodeSpawned.name}...");
m_NextNodeSpawned.PingInstance();
}
else
@@ -178,11 +205,13 @@ public override void OnNetworkDespawn()
private void InvokeDespawn()
{
+ Log($"Despawn with defer started! DeferDespawnTick = {DeferDespawnTick}");
if (!HasAuthority)
{
FailTest($"[{nameof(InvokeDespawn)}] Client is not the authority but this was invoked (integration test logic issue)!");
}
NetworkObject.DeferDespawn(DeferDespawnTick);
+ Log($"Should despawn on tick {DeferDespawnTick + NetworkManager.ServerTime.Tick}...");
}
public override void OnDeferringDespawn(int despawnTick)
@@ -196,13 +225,13 @@ public override void OnDeferringDespawn(int despawnTick)
{
FailTest($"[{nameof(OnDeferringDespawn)}] The passed in {despawnTick} parameter ({despawnTick}) does not equal the expected value of ({DeferDespawnTick + NetworkManager.ServerTime.Tick})!");
}
-
+ Log($"[OnDeferringDespawn] Deferring despawn...");
if (PrefabToSpawnWhenDespawned != null)
{
var deferNetworkObject = PrefabToSpawnWhenDespawned.GetComponent().InstantiateAndSpawn(NetworkManager);
var deferComponent = deferNetworkObject.GetComponent();
// Slowly increment the despawn tick count as we process the chain of deferred despawns
- deferComponent.DeferDespawnTick = DeferDespawnTick + 1;
+ deferComponent.DeferDespawnTick = k_StartingDeferTick + 1;
// This should get updated on all non-authority instances before they despawn
m_ValidateDirtyNetworkVarUpdate.Value = new NetworkBehaviourReference(deferComponent);
}
@@ -214,13 +243,17 @@ public override void OnDeferringDespawn(int despawnTick)
}
private bool m_DeferredDespawn;
+ private bool m_InstantiatedObject;
+ private float m_TickDelay;
+
+ private DeferredDespawnDaisyChained m_DeferredComponent;
+ private NetworkObject m_DeferredObject;
private void Update()
{
if (!IsSpawned || !HasAuthority || m_DeferredDespawn)
{
return;
}
-
// Wait until all clients have this instance
foreach (var clientId in NetworkManager.ConnectedClientsIds)
{
@@ -248,8 +281,6 @@ private void Update()
return;
}
}
-
- // If we made it here, then defer despawn this instance
InvokeDespawn();
m_DeferredDespawn = true;
}
@@ -260,7 +291,7 @@ private void Log(string message)
{
return;
}
- Debug.Log($"[{name}][Client-{NetworkManager.LocalClientId}][{NetworkObjectId}] {message}");
+ Debug.Log($"[{name}][Client-{NetworkManager.LocalClientId}][{NetworkObjectId}][{NetworkManager.ServerTime.Tick}][DD: {NetworkManager.ServerTime.Tick + DeferDespawnTick}] {message}");
}
}
}
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs
index 7957e6cf0c..8c018e0f00 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DistributeObjectsTests.cs
@@ -6,7 +6,6 @@
using NUnit.Framework;
using Unity.Netcode.Components;
using Unity.Netcode.TestHelpers.Runtime;
-using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.TestTools;
using Random = UnityEngine.Random;
@@ -17,6 +16,7 @@ namespace Unity.Netcode.RuntimeTests
/// Validates that distributable NetworkObjects are distributed upon
/// a client connecting or disconnecting.
///
+ [TestFixture(HostOrServer.DAHost)]
internal class DistributeObjectsTests : IntegrationTestWithApproximation
{
private GameObject m_DistributeObject;
@@ -26,8 +26,11 @@ internal class DistributeObjectsTests : IntegrationTestWithApproximation
private const int k_LateJoinClientCount = 4;
protected override int NumberOfClients => 0;
- public DistributeObjectsTests() : base(HostOrServer.DAHost)
+ private NetworkManager m_SessionOwner;
+
+ public DistributeObjectsTests(HostOrServer hostOrServer) : base(hostOrServer)
{
+
}
protected override IEnumerator OnSetup()
@@ -38,9 +41,7 @@ protected override IEnumerator OnSetup()
protected override void OnServerAndClientsCreated()
{
- var serverTransport = m_ServerNetworkManager.NetworkConfig.NetworkTransport as UnityTransport;
- // I hate having to add time to our tests, but in case a VM is running slow the disconnect timeout needs to be reasonably high
- serverTransport.DisconnectTimeoutMS = 1000;
+
m_DistributeObject = CreateNetworkObjectPrefab("DisObject");
m_DistributeObject.AddComponent();
m_DistributeObject.AddComponent();
@@ -54,8 +55,12 @@ protected override void OnServerAndClientsCreated()
protected override IEnumerator OnServerAndClientsConnected()
{
- m_ServerNetworkManager.SpawnManager.EnableDistributeLogging = m_EnableVerboseDebug;
- m_ServerNetworkManager.ConnectionManager.EnableDistributeLogging = m_EnableVerboseDebug;
+ if (!UseCMBService())
+ {
+ m_ServerNetworkManager.SpawnManager.EnableDistributeLogging = m_EnableVerboseDebug;
+ m_ServerNetworkManager.ConnectionManager.EnableDistributeLogging = m_EnableVerboseDebug;
+ }
+
return base.OnServerAndClientsConnected();
}
@@ -67,9 +72,9 @@ private bool ValidateObjectSpawnedOnAllClients()
var networkObjectId = m_ObjectToValidate.NetworkObjectId;
var name = m_ObjectToValidate.name;
- if (!UseCMBService() && !m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId))
+ if (!UseCMBService() && !m_SessionOwner.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId))
{
- m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} has not spawned {name}!");
+ m_ErrorLog.Append($"Client-{m_SessionOwner.LocalClientId} has not spawned {name}!");
return false;
}
@@ -89,7 +94,7 @@ private bool ValidateObjectSpawnedOnAllClients()
private bool ValidateDistributedObjectsSpawned(bool lateJoining)
{
m_ErrorLog.Clear();
- var hostId = m_ServerNetworkManager.LocalClientId;
+ var hostId = m_SessionOwner.LocalClientId;
if (!DistributeObjectsTestHelper.DistributedObjects.ContainsKey(hostId))
{
m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have an entry in the root of the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!");
@@ -104,13 +109,14 @@ private bool ValidateDistributedObjectsSpawned(bool lateJoining)
var daHostObjects = daHostObjectTracking[hostId];
var expected = 0;
+ var offset = UseCMBService() ? 0 : 1;
if (lateJoining)
{
- expected = k_ObjectCount / (m_ClientNetworkManagers.Count() + 1);
+ expected = k_ObjectCount / (m_ClientNetworkManagers.Count() + offset);
}
else
{
- expected = k_ObjectCount / (m_ClientNetworkManagers.Where((c) => c.IsConnectedClient).Count() + 1);
+ expected = k_ObjectCount / (m_ClientNetworkManagers.Where((c) => c.IsConnectedClient).Count() + offset);
}
// It should theoretically be the expected or...
@@ -140,8 +146,9 @@ private bool ValidateDistributedObjectsSpawned(bool lateJoining)
private bool ValidateOwnershipTablesMatch()
{
m_ErrorLog.Clear();
- var hostId = m_ServerNetworkManager.LocalClientId;
- var expectedEntries = m_ClientNetworkManagers.Where((c) => c.IsListening && c.IsConnectedClient).Count() + 1;
+ var hostId = m_SessionOwner.LocalClientId;
+ var offset = UseCMBService() ? 0 : 1;
+ var expectedEntries = m_ClientNetworkManagers.Where((c) => c.IsListening && c.IsConnectedClient).Count() + offset;
// Make sure all clients have an table created
if (DistributeObjectsTestHelper.DistributedObjects.Count < expectedEntries)
{
@@ -160,16 +167,22 @@ private bool ValidateOwnershipTablesMatch()
m_ErrorLog.AppendLine($"[Client-{hostId}] Does not have a local an entry in the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!");
return false;
}
- var clients = m_ServerNetworkManager.ConnectedClientsIds.ToList();
+ var clients = m_SessionOwner.ConnectedClientsIds.ToList();
clients.Remove(0);
- // Cycle through each client's entry on the DAHost to run a comparison
+ // Cycle through each client's entry on the session owner side to run a comparison
foreach (var hostClientEntry in daHostEntries)
{
foreach (var ownerEntry in hostClientEntry.Value)
{
foreach (var client in clients)
{
+ if (!DistributeObjectsTestHelper.DistributedObjects.ContainsKey(client))
+ {
+ m_ErrorLog.AppendLine($"[Client-{client}] Does not have a local an entry in the {nameof(DistributeObjectsTestHelper.DistributedObjects)} table!");
+ return false;
+ }
+
var clientOwnerTable = DistributeObjectsTestHelper.DistributedObjects[client];
if (!clientOwnerTable.ContainsKey(hostClientEntry.Key))
{
@@ -206,9 +219,9 @@ private bool ValidateOwnershipTablesMatch()
private bool ValidateTransformsMatch()
{
m_ErrorLog.Clear();
- var hostId = m_ServerNetworkManager.LocalClientId;
+ var hostId = m_SessionOwner.LocalClientId;
var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[hostId];
- var clients = m_ServerNetworkManager.ConnectedClientsIds.ToList();
+ var clients = m_SessionOwner.ConnectedClientsIds.ToList();
foreach (var clientOwner in daHostEntries.Keys)
{
// Cycle through the owner's objects
@@ -237,23 +250,27 @@ private bool ValidateTransformsMatch()
protected override void OnNewClientCreated(NetworkManager networkManager)
{
- networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs;
+ if (UseCMBService() && m_SessionOwner == null)
+ {
+ networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs;
+ }
+ else
+ {
+ networkManager.NetworkConfig.Prefabs = m_SessionOwner.NetworkConfig.Prefabs;
+ }
+ //networkManager.NetworkConfig.AutoSpawnPlayerPrefabClientSide = false;
+ //networkManager.NetworkConfig.EnableSceneManagement = false;
+
+
base.OnNewClientCreated(networkManager);
}
private bool SpawnCountsMatch()
{
var passed = true;
- var spawnCount = 0;
m_ErrorLog.Clear();
- if (!UseCMBService())
- {
- spawnCount = m_ServerNetworkManager.SpawnManager.SpawnedObjects.Count;
- }
- else
- {
- spawnCount = m_ClientNetworkManagers[0].SpawnManager.SpawnedObjects.Count;
- }
+ var spawnCount = m_SessionOwner.SpawnManager.SpawnedObjects.Count;
+
foreach (var client in m_ClientNetworkManagers)
{
var clientCount = client.SpawnManager.SpawnedObjects.Count;
@@ -276,13 +293,21 @@ private bool SpawnCountsMatch()
[UnityTest]
public IEnumerator DistributeNetworkObjects()
{
+ var clientIndexOffset = 0;
+ if (UseCMBService())
+ {
+ clientIndexOffset++;
+ yield return CreateAndStartNewClient();
+ }
+
+ m_SessionOwner = GetSessionOwner();
for (int i = 0; i < k_ObjectCount; i++)
{
- SpawnObject(m_DistributeObject, m_ServerNetworkManager);
+ SpawnObject(m_DistributeObject, m_SessionOwner);
}
// Validate NetworkObjects get redistributed properly when a client joins
- for (int j = 0; j < k_LateJoinClientCount; j++)
+ for (int j = clientIndexOffset; j < k_LateJoinClientCount + clientIndexOffset; j++)
{
yield return CreateAndStartNewClient();
@@ -303,10 +328,16 @@ public IEnumerator DistributeNetworkObjects()
AssertOnTimeout($"[Spawn Count Mismatch] {m_ErrorLog}");
}
+ var clientStartIndex = m_ClientNetworkManagers.Length;
+
// Validate NetworkObjects get redistributed properly when a client disconnects
- for (int j = k_LateJoinClientCount - 1; j >= 0; j--)
+ for (int j = k_LateJoinClientCount - 1 + clientIndexOffset; j >= 0; j--)
{
var client = m_ClientNetworkManagers[j];
+ if (UseCMBService() && client.LocalClient.IsSessionOwner)
+ {
+ continue;
+ }
// Remove the client from the other clients' ownership tracking table
DistributeObjectsTestHelper.RemoveClient(client.LocalClientId);
@@ -314,8 +345,6 @@ public IEnumerator DistributeNetworkObjects()
// Disconnect the client
yield return StopOneClient(client, true);
- //yield return new WaitForSeconds(0.1f);
-
// Validate all tables match
yield return WaitForConditionOrTimeOut(ValidateOwnershipTablesMatch);
@@ -338,7 +367,8 @@ public IEnumerator DistributeNetworkObjects()
private void DisplayOwnership()
{
m_ErrorLog.Clear();
- var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[0];
+ var startingIndex = (ulong)(UseCMBService() ? 1 : 0);
+ var daHostEntries = DistributeObjectsTestHelper.DistributedObjects[startingIndex];
foreach (var entry in daHostEntries)
{
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs
index d7890c202f..289f611485 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/NetworkClientAndPlayerObjectTests.cs
@@ -22,7 +22,6 @@ internal class NetworkClientAndPlayerObjectTests : NetcodeIntegrationTest
private List m_PlayerPrefabs = new List();
private Dictionary m_ChangedPlayerPrefabs = new Dictionary();
-
public NetworkClientAndPlayerObjectTests(HostOrServer hostOrServer) : base(hostOrServer)
{
}
@@ -45,7 +44,8 @@ protected override void OnServerAndClientsCreated()
protected override void OnNewClientCreated(NetworkManager networkManager)
{
- networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs;
+ var sessionOwner = GetSessionOwner();
+ networkManager.NetworkConfig.Prefabs = sessionOwner.NetworkConfig.Prefabs;
if (m_DistributedAuthority)
{
networkManager.OnFetchLocalPlayerPrefabToSpawn = FetchPlayerPrefabToSpawn;
@@ -101,7 +101,7 @@ private bool ValidateNetworkManagerNetworkClients(NetworkManager networkManager)
m_ErrorLogLevel2.Clear();
// Number of connected clients plus the DAHost
- var expectedCount = m_ClientNetworkManagers.Length + (m_UseHost ? 1 : 0);
+ var expectedCount = UseCMBService() ? m_ClientNetworkManagers.Length : m_ClientNetworkManagers.Length + (m_UseHost ? 1 : 0);
if (networkManager.ConnectedClients.Count != expectedCount)
{
@@ -265,7 +265,7 @@ public IEnumerator ValidatePlayerObjects()
m_ChangedPlayerPrefabs.Clear();
var playerInstance = (GameObject)null;
var playerPrefabToSpawn = (NetworkObject)null;
- if (m_UseHost)
+ if (m_UseHost && !UseCMBService())
{
playerPrefabToSpawn = GetRandomPlayerPrefab();
playerInstance = SpawnPlayerObject(playerPrefabToSpawn.gameObject, m_ServerNetworkManager);
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs
index beccbdd9db..0f6e45b14d 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs
@@ -6,18 +6,22 @@
using Unity.Netcode.TestHelpers.Runtime;
using UnityEngine;
using UnityEngine.TestTools;
+using Object = UnityEngine.Object;
namespace Unity.Netcode.RuntimeTests
{
+ [TestFixture(HostOrServer.DAHost)]
internal class OwnershipPermissionsTests : IntegrationTestWithApproximation
{
private GameObject m_PermissionsObject;
private StringBuilder m_ErrorLog = new StringBuilder();
+ private NetworkManager m_SessionOwner;
+
protected override int NumberOfClients => 4;
- public OwnershipPermissionsTests() : base(HostOrServer.DAHost)
+ public OwnershipPermissionsTests(HostOrServer hostOrServer) : base(hostOrServer)
{
}
@@ -28,11 +32,20 @@ protected override IEnumerator OnSetup()
return base.OnSetup();
}
+ ///
+ /// This is where the client NetworkManagers are configured
+ ///
protected override void OnServerAndClientsCreated()
{
m_PermissionsObject = CreateNetworkObjectPrefab("PermObject");
m_PermissionsObject.AddComponent();
-
+ Object.DontDestroyOnLoad(m_PermissionsObject);
+ m_PermissionsObject.gameObject.SetActive(false);
+ foreach (var client in m_ClientNetworkManagers)
+ {
+ client.NetworkConfig.NetworkTopology = NetworkTopologyTypes.DistributedAuthority;
+ client.NetworkConfig.UseCMBService = UseCMBServiceForDATests;
+ }
base.OnServerAndClientsCreated();
}
@@ -44,9 +57,9 @@ private bool ValidateObjectSpawnedOnAllClients()
var networkObjectId = m_ObjectToValidate.NetworkObjectId;
var name = m_ObjectToValidate.name;
- if (!UseCMBService() && !m_ServerNetworkManager.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId))
+ if (!UseCMBService() && !m_SessionOwner.SpawnManager.SpawnedObjects.ContainsKey(networkObjectId))
{
- m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} has not spawned {name}!");
+ m_ErrorLog.Append($"Client-{m_SessionOwner.LocalClientId} has not spawned {name}!");
return false;
}
@@ -70,10 +83,10 @@ private bool ValidatePermissionsOnAllClients()
m_ErrorLog.Clear();
if (!UseCMBService())
{
- otherPermissions = (ushort)m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId].Ownership;
+ otherPermissions = (ushort)m_SessionOwner.SpawnManager.SpawnedObjects[networkObjectId].Ownership;
if (currentPermissions != otherPermissions)
{
- m_ErrorLog.Append($"Client-{m_ServerNetworkManager.LocalClientId} permissions for {objectName} is {otherPermissions} when it should be {currentPermissions}!");
+ m_ErrorLog.Append($"Client-{m_SessionOwner.LocalClientId} permissions for {objectName} is {otherPermissions} when it should be {currentPermissions}!");
return false;
}
}
@@ -97,10 +110,10 @@ private bool ValidateAllInstancesAreOwnedByClient(ulong clientId)
m_ErrorLog.Clear();
if (!UseCMBService())
{
- otherNetworkObject = m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId];
+ otherNetworkObject = m_SessionOwner.SpawnManager.SpawnedObjects[networkObjectId];
if (otherNetworkObject.OwnerClientId != clientId)
{
- m_ErrorLog.Append($"[Client-{m_ServerNetworkManager.LocalClientId}][{otherNetworkObject.name}] Expected owner to be {clientId} but it was {otherNetworkObject.OwnerClientId}!");
+ m_ErrorLog.Append($"[Client-{m_SessionOwner.LocalClientId}][{otherNetworkObject.name}] Expected owner to be {clientId} but it was {otherNetworkObject.OwnerClientId}!");
return false;
}
}
@@ -120,7 +133,11 @@ private bool ValidateAllInstancesAreOwnedByClient(ulong clientId)
[UnityTest]
public IEnumerator ValidateOwnershipPermissionsTest()
{
- var firstInstance = SpawnObject(m_PermissionsObject, m_ClientNetworkManagers[0]).GetComponent();
+ m_SessionOwner = GetSessionOwner();
+
+ m_PermissionsObject.gameObject.SetActive(true);
+ yield return null;
+ var firstInstance = SpawnObject(m_PermissionsObject, m_SessionOwner).GetComponent();
OwnershipPermissionsTestHelper.CurrentOwnedInstance = firstInstance;
var firstInstanceHelper = firstInstance.GetComponent();
var networkObjectId = firstInstance.NetworkObjectId;
@@ -243,12 +260,12 @@ public IEnumerator ValidateOwnershipPermissionsTest()
// Get the 3rd client to send a request at the "relatively" same time
var thirdInstance = m_ClientNetworkManagers[2].SpawnManager.SpawnedObjects[networkObjectId];
var thirdInstanceHelper = thirdInstance.GetComponent();
-
+ yield return null;
// At the same time send a request by the third client.
requestStatus = thirdInstance.RequestOwnership();
// We expect the 3rd client's request should be able to be sent at this time as well (i.e. creates the race condition between two clients)
- Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{m_ServerNetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
+ Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{m_SessionOwner.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
// We expect the first requesting client to be given ownership
yield return WaitForConditionOrTimeOut(() => firstInstance.IsOwner);
@@ -256,7 +273,8 @@ public IEnumerator ValidateOwnershipPermissionsTest()
m_ObjectToValidate = OwnershipPermissionsTestHelper.CurrentOwnedInstance;
// Just do a sanity check to assure ownership has changed on all clients.
- yield return WaitForConditionOrTimeOut(() => ValidateAllInstancesAreOwnedByClient(firstInstance.NetworkManager.LocalClientId));
+ yield return WaitForConditionOrTimeOut(() => ValidateAllInstancesAreOwnedByClient(firstInstance.NetworkManager.LocalClientId)); // <---- Failes here
+
AssertOnTimeout($"[Ownership Mismatch] {firstInstance.name}: \n {m_ErrorLog}");
// Now, the third client should get a RequestInProgress returned as their request response
@@ -304,32 +322,30 @@ public IEnumerator ValidateOwnershipPermissionsTest()
// Test for targeted ownership request:
///////////////////////////////////////////////
- // Now get the DAHost's client's instance
- var daHostInstance = m_ServerNetworkManager.SpawnManager.SpawnedObjects[networkObjectId];
- var daHostInstanceHelper = daHostInstance.GetComponent();
+ var targetApprovedNetworkObject = firstInstance;
+ var targetApprovedTestHelper = firstInstanceHelper;
+ firstInstanceHelper = null;
secondInstanceHelper.AllowOwnershipRequest = true;
secondInstanceHelper.OnlyAllowTargetClientId = true;
- secondInstanceHelper.ClientToAllowOwnership = daHostInstance.NetworkManager.LocalClientId;
+ secondInstanceHelper.ClientToAllowOwnership = targetApprovedNetworkObject.NetworkManager.LocalClientId;
- // Send out a request from all three clients
- requestStatus = firstInstance.RequestOwnership();
- Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{firstInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
requestStatus = thirdInstance.RequestOwnership();
Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{thirdInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
requestStatus = fourthInstance.RequestOwnership();
Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{fourthInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
- requestStatus = daHostInstance.RequestOwnership();
- Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{daHostInstance.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
+ requestStatus = targetApprovedNetworkObject.RequestOwnership();
+ Assert.True(requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent, $"Client-{targetApprovedNetworkObject.NetworkManager.LocalClientId} was unabled to send a request for ownership because: {requestStatus}!");
- // The server and the 2nd client should be denied and the third client should be approved
yield return WaitForConditionOrTimeOut(() =>
- (firstInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) &&
- (thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) &&
- (fourthInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied) &&
- (daHostInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Approved)
+ (thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied || thirdInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.RequestInProgress) &&
+ (fourthInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Denied || fourthInstanceHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.RequestInProgress) &&
+ (targetApprovedTestHelper.OwnershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Approved)
);
- AssertOnTimeout($"[Targeted Owner] Client-{daHostInstance.NetworkManager.LocalClientId} did not get the right request reponse: {daHostInstanceHelper.OwnershipRequestResponseStatus} Expecting: {NetworkObject.OwnershipRequestResponseStatus.Approved}!");
+
+ AssertOnTimeout($"[Targeted Owner] Client-{targetApprovedTestHelper.NetworkManager.LocalClientId} did not get the right request reponse: {targetApprovedTestHelper.OwnershipRequestResponseStatus} Expecting: {NetworkObject.OwnershipRequestResponseStatus.Approved}!");
+
+ yield return s_DefaultWaitForTick;
}
internal class OwnershipPermissionsTestHelper : NetworkBehaviour
diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs
index 9a7a9f8557..a741d23a69 100644
--- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs
+++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs
@@ -3,6 +3,7 @@
using System.Text;
using NUnit.Framework;
using Unity.Netcode.TestHelpers.Runtime;
+using UnityEngine.TestTools;
namespace Unity.Netcode.RuntimeTests
{
@@ -13,14 +14,13 @@ namespace Unity.Netcode.RuntimeTests
/// so we can validate these issues. While this test does
/// partially validate it we still need to manually validate
/// with a service connection.
- ///
- [TestFixture(HostOrServer.Host)]
+ ///
[TestFixture(HostOrServer.DAHost)]
public class RpcProxyMessageTesting : NetcodeIntegrationTest
{
- protected override int NumberOfClients => 2;
+ protected override int NumberOfClients => 4;
- private List m_ProxyTestInstances = new List();
+ private List m_ProxyTestInstances = new List();
private StringBuilder m_ValidationLogger = new StringBuilder();
@@ -34,7 +34,7 @@ protected override IEnumerator OnSetup()
protected override void OnCreatePlayerPrefab()
{
- m_PlayerPrefab.AddComponent();
+ m_PlayerPrefab.AddComponent();
base.OnCreatePlayerPrefab();
}
@@ -44,28 +44,38 @@ private bool ValidateRpcProxyRpcs()
m_ValidationLogger.Clear();
foreach (var proxy in m_ProxyTestInstances)
{
- if (proxy.ReceivedRpc.Count < NumberOfClients)
+ foreach (var client in m_ClientNetworkManagers)
{
- m_ValidationLogger.AppendLine($"Not all clients received RPC from Client-{proxy.OwnerClientId}!");
- }
- foreach (var clientId in proxy.ReceivedRpc)
- {
- if (clientId == proxy.OwnerClientId)
+ if (client.LocalClientId == proxy.OwnerClientId)
{
- m_ValidationLogger.AppendLine($"Client-{proxy.OwnerClientId} sent itself an Rpc!");
+ continue;
}
+ var playerClone = m_PlayerNetworkObjects[client.LocalClientId][proxy.OwnerClientId];
+ var proxyClone = playerClone.GetComponent();
+ if (proxyClone.ReceivedRpc.Count != 1)
+ {
+ m_ValidationLogger.AppendLine($"[Client-{client.LocalClientId}] Did not receive an RPC from Client-{proxy.OwnerClientId}!");
+ }
+ }
+ if (proxy.ReceivedRpc.Contains(proxy.OwnerClientId))
+ {
+ m_ValidationLogger.AppendLine($"Client-{proxy.OwnerClientId} sent itself an Rpc!");
}
}
return m_ValidationLogger.Length == 0;
}
-
+ [UnityTest]
public IEnumerator ProxyDoesNotInvokeOnSender()
{
- m_ProxyTestInstances.Add(m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent());
+ if (!UseCMBService())
+ {
+ m_ProxyTestInstances.Add(m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent());
+ }
+
foreach (var client in m_ClientNetworkManagers)
{
- m_ProxyTestInstances.Add(client.LocalClient.PlayerObject.GetComponent());
+ m_ProxyTestInstances.Add(client.LocalClient.PlayerObject.GetComponent());
}
foreach (var clientProxyTest in m_ProxyTestInstances)
@@ -77,7 +87,7 @@ public IEnumerator ProxyDoesNotInvokeOnSender()
AssertOnTimeout(m_ValidationLogger.ToString());
}
- public class RpcProxyText : NetworkBehaviour
+ public class RpcProxyTest : NetworkBehaviour
{
public List ReceivedRpc = new List();
diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventNotifications.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventNotifications.cs
index 34a2078499..90cf111146 100644
--- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventNotifications.cs
+++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerEventNotifications.cs
@@ -72,7 +72,10 @@ protected override IEnumerator OnTearDown()
protected override IEnumerator OnStartedServerAndClients()
{
- m_ServerNetworkManager.SceneManager.OnSceneEvent += ServerSceneManager_OnSceneEvent;
+ if (!UseCMBService())
+ {
+ m_ServerNetworkManager.SceneManager.OnSceneEvent += ServerSceneManager_OnSceneEvent;
+ }
foreach (var client in m_ClientNetworkManagers)
{
client.SceneManager.ClientSynchronizationMode = m_LoadSceneMode;
@@ -90,7 +93,7 @@ private void ClientSceneManager_OnSceneEvent(SceneEvent sceneEvent)
{
var matchedClient = m_ClientNetworkManagers.Where(c => c.LocalClientId == sceneEvent.ClientId);
Assert.True(matchedClient.Count() > 0, $"Found no client {nameof(NetworkManager)}s that had a {nameof(NetworkManager.LocalClientId)} of {sceneEvent.ClientId}");
- Assert.AreEqual(matchedClient.First().SceneManager.ClientSynchronizationMode, m_ServerNetworkManager.SceneManager.ClientSynchronizationMode);
+ Assert.AreEqual(matchedClient.First().SceneManager.ClientSynchronizationMode, m_SessionOwner.SceneManager.ClientSynchronizationMode);
break;
}
}
@@ -98,6 +101,7 @@ private void ClientSceneManager_OnSceneEvent(SceneEvent sceneEvent)
private void ServerSceneManager_OnSceneEvent(SceneEvent sceneEvent)
{
+ var clientCompleted = UseCMBService() ? m_ClientNetworkManagers[1] : m_ClientNetworkManagers[0];
VerboseDebug($"[SceneEvent] ClientId:{sceneEvent.ClientId} | EventType: {sceneEvent.SceneEventType}");
switch (sceneEvent.SceneEventType)
{
@@ -120,12 +124,13 @@ private void ServerSceneManager_OnSceneEvent(SceneEvent sceneEvent)
}
case SceneEventType.LoadComplete:
{
- if (sceneEvent.ClientId == NetworkManager.ServerClientId)
+ if (sceneEvent.ClientId == m_SessionOwner.LocalClientId)
{
var scene = sceneEvent.Scene;
m_CurrentScene = scene;
}
- if (sceneEvent.ClientId == m_ClientNetworkManagers[0].LocalClientId)
+
+ if (sceneEvent.ClientId == clientCompleted.LocalClientId)
{
if (!m_ScenesLoaded.Contains(sceneEvent.SceneName))
{
@@ -156,10 +161,10 @@ private void ServerSceneManager_OnSceneEvent(SceneEvent sceneEvent)
// If we are a server and this is being processed by the server, then add the server to the completed list
// to validate that the event completed on all clients (and the server).
- if (!m_ServerNetworkManager.IsHost && sceneEvent.ClientId == m_ServerNetworkManager.LocalClientId &&
- !sceneEvent.ClientsThatCompleted.Contains(m_ServerNetworkManager.LocalClientId))
+ if (!m_SessionOwner.IsServer && sceneEvent.ClientId == m_SessionOwner.LocalClientId &&
+ !sceneEvent.ClientsThatCompleted.Contains(m_SessionOwner.LocalClientId))
{
- sceneEvent.ClientsThatCompleted.Add(m_ServerNetworkManager.LocalClientId);
+ sceneEvent.ClientsThatCompleted.Add(m_SessionOwner.LocalClientId);
}
if (sceneEvent.SceneEventType == SceneEventType.LoadEventCompleted)
{
@@ -213,6 +218,7 @@ protected override bool CanStartServerAndClients()
return m_CanStartServerOrClients;
}
+ private NetworkManager m_SessionOwner;
///
/// Tests the different types of NetworkSceneManager notifications (including exceptions) generated
/// Also tests invalid loading scenarios (i.e. client trying to load a scene)
@@ -220,6 +226,7 @@ protected override bool CanStartServerAndClients()
[UnityTest]
public IEnumerator SceneLoadingAndNotifications([Values] LoadSceneMode loadSceneMode)
{
+ m_SessionOwner = UseCMBService() ? m_ClientNetworkManagers[0] : m_ServerNetworkManager;
m_LoadSceneMode = loadSceneMode;
m_CurrentSceneName = k_SceneToLoad;
@@ -237,9 +244,9 @@ public IEnumerator SceneLoadingAndNotifications([Values] LoadSceneMode loadScene
// Test loading scenes and the associated event messaging and notification pipelines
ResetWait();
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.Started);
+ Assert.AreEqual(m_SessionOwner.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.Started);
// Check error status for trying to load during an already in progress scene event
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.SceneEventInProgress);
+ Assert.AreEqual(m_SessionOwner.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.SceneEventInProgress);
// Wait for all clients to load the scene
yield return WaitForConditionOrTimeOut(ConditionPassed);
@@ -256,7 +263,7 @@ public IEnumerator SceneLoadingAndNotifications([Values] LoadSceneMode loadScene
m_CurrentSceneName = k_InSceneNetworkObject;
ResetWait();
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.LoadScene(k_InSceneNetworkObject, LoadSceneMode.Additive), SceneEventProgressStatus.Started);
+ Assert.AreEqual(m_SessionOwner.SceneManager.LoadScene(k_InSceneNetworkObject, LoadSceneMode.Additive), SceneEventProgressStatus.Started);
// Wait for all clients to additively load this additional scene
yield return WaitForConditionOrTimeOut(ConditionPassed);
@@ -266,7 +273,7 @@ public IEnumerator SceneLoadingAndNotifications([Values] LoadSceneMode loadScene
// Now single mode load a new scene (i.e. "scene switch")
m_CurrentSceneName = k_BaseUnitTestSceneName;
ResetWait();
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.Started);
+ Assert.AreEqual(m_SessionOwner.SceneManager.LoadScene(m_CurrentSceneName, loadSceneMode), SceneEventProgressStatus.Started);
// Wait for all clients to perform scene switch
yield return WaitForConditionOrTimeOut(ConditionPassed);
AssertOnTimeout($"Timed out waiting for all clients to switch to scene {m_CurrentSceneName}!");
@@ -288,18 +295,18 @@ public IEnumerator SceneLoadingAndNotifications([Values] LoadSceneMode loadScene
// Test unloading additive scenes and the associated event messaging and notification pipelines
ResetWait();
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.UnloadScene(m_CurrentScene), SceneEventProgressStatus.Started);
+ Assert.AreEqual(m_SessionOwner.SceneManager.UnloadScene(m_CurrentScene), SceneEventProgressStatus.Started);
yield return WaitForConditionOrTimeOut(ConditionPassed);
AssertOnTimeout($"Timed out waiting for all clients to unload {m_CurrentSceneName}!");
// Check error status for trying to unloading something not loaded
ResetWait();
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.UnloadScene(m_CurrentScene), SceneEventProgressStatus.SceneNotLoaded);
+ Assert.AreEqual(m_SessionOwner.SceneManager.UnloadScene(m_CurrentScene), SceneEventProgressStatus.SceneNotLoaded);
// Check error status for trying to load an invalid scene name
LogAssert.Expect(LogType.Error, $"Scene '{k_InvalidSceneName}' couldn't be loaded because it has not been added to the build settings scenes in build list.");
- Assert.AreEqual(m_ServerNetworkManager.SceneManager.LoadScene(k_InvalidSceneName, LoadSceneMode.Additive), SceneEventProgressStatus.InvalidSceneName);
+ Assert.AreEqual(m_SessionOwner.SceneManager.LoadScene(k_InvalidSceneName, LoadSceneMode.Additive), SceneEventProgressStatus.InvalidSceneName);
}