diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs
index d9918dc61d..b7dd37d2a0 100644
--- a/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs
+++ b/com.unity.multiplayer.mlapi/Tests/Runtime/MultiInstance/MultiInstanceHelpers.cs
@@ -6,14 +6,18 @@
using NUnit.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;
+using Object = UnityEngine.Object;
namespace MLAPI.RuntimeTests
{
///
/// Provides helpers for running multi instance tests.
///
- internal static class MultiInstanceHelpers
+ public static class MultiInstanceHelpers
{
+
+ public static List NetworkManagerInstances = new List();
+
///
/// Creates NetworkingManagers and configures them for use in a multi instance setting.
///
@@ -28,11 +32,10 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
{
// Create gameObject
var go = new GameObject("NetworkManager - Client - " + i);
-
// Create networkManager component
clients[i] = go.AddComponent();
- // Set config
+ // Set the NetworkConfig
clients[i].NetworkConfig = new NetworkConfig()
{
// Set the current scene to prevent unexpected log messages which would trigger a failure
@@ -42,14 +45,17 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
};
}
+ NetworkManagerInstances = new List(clients);
+
{
// Create gameObject
var go = new GameObject("NetworkManager - Server");
// Create networkManager component
server = go.AddComponent();
+ NetworkManagerInstances.Insert(0, server);
- // Set config
+ // Set the NetworkConfig
server.NetworkConfig = new NetworkConfig()
{
// Set the current scene to prevent unexpected log messages which would trigger a failure
@@ -62,6 +68,25 @@ public static bool Create(int clientCount, out NetworkManager server, out Networ
return true;
}
+
+ public static void ShutdownAndClean()
+ {
+ // Shutdown the server which forces clients to disconnect
+ foreach (var networkManager in NetworkManagerInstances)
+ {
+ if (networkManager.IsServer)
+ {
+ networkManager.StopHost();
+ }
+ }
+
+ // Destroy the network manager instances
+ foreach (var networkManager in NetworkManagerInstances)
+ {
+ Object.Destroy(networkManager.gameObject);
+ }
+ }
+
///
/// Starts NetworkManager instances created by the Create method.
///
@@ -170,6 +195,52 @@ public static IEnumerator WaitForClientConnected(NetworkManager client, Coroutin
}
}
+ public static IEnumerator WaitForClientsConnected(NetworkManager[] clients, CoroutineResultWrapper result = null, int maxFrames = 64)
+ {
+ // Make sure none are the host client
+ foreach (var client in clients)
+ {
+ if (client.IsServer)
+ {
+ throw new InvalidOperationException("Cannot wait for connected as server");
+ }
+ }
+
+
+ int startFrame = Time.frameCount;
+ var allConnected = true;
+ while (Time.frameCount - startFrame <= maxFrames)
+ {
+ allConnected = true;
+ foreach (var client in clients)
+ {
+ if (!client.IsConnectedClient)
+ {
+ allConnected = false;
+ break;
+ }
+ }
+ if (allConnected)
+ {
+ break;
+ }
+ int nextFrameId = Time.frameCount + 1;
+ yield return new WaitUntil(() => Time.frameCount >= nextFrameId);
+ }
+
+ if (result != null)
+ {
+ result.Result = allConnected;
+ }
+ else
+ {
+ foreach (var client in clients)
+ {
+ Assert.True(client.IsConnectedClient, $"Client {client.LocalClientId} never connected");
+ }
+ }
+ }
+
///
/// Waits on the server side for 1 client to be connected
///
@@ -199,7 +270,40 @@ public static IEnumerator WaitForClientConnectedToServer(NetworkManager server,
}
else
{
- Assert.True(res, "Client never connected to server");
+ Assert.True(res, "A Client never connected to server");
+ }
+ }
+
+ ///
+ /// Waits on the server side for 1 client to be connected
+ ///
+ /// The server
+ /// The result. If null, it will automatically assert
+ /// The max frames to wait for
+ public static IEnumerator WaitForClientsConnectedToServer(NetworkManager server, int clientCount, CoroutineResultWrapper result = null, int maxFrames = 64)
+ {
+ if (!server.IsServer)
+ {
+ throw new InvalidOperationException("Cannot wait for connected as client");
+ }
+
+ int startFrame = Time.frameCount;
+
+ while (Time.frameCount - startFrame <= maxFrames && server.ConnectedClients.Count != clientCount)
+ {
+ int nextFrameId = Time.frameCount + 1;
+ yield return new WaitUntil(() => Time.frameCount >= nextFrameId);
+ }
+
+ bool res = server.ConnectedClients.Count == clientCount;
+
+ if (result != null)
+ {
+ result.Result = res;
+ }
+ else
+ {
+ Assert.True(res, "A client never connected to server");
}
}
diff --git a/com.unity.multiplayer.mlapi/Tests/Runtime/Transport/SIPTransport.cs b/com.unity.multiplayer.mlapi/Tests/Runtime/Transport/SIPTransport.cs
index c86ab36c69..866d6b8019 100644
--- a/com.unity.multiplayer.mlapi/Tests/Runtime/Transport/SIPTransport.cs
+++ b/com.unity.multiplayer.mlapi/Tests/Runtime/Transport/SIPTransport.cs
@@ -44,24 +44,35 @@ public override void DisconnectLocalClient()
{
Type = NetworkEvent.Disconnect,
Channel = NetworkChannel.Internal,
- ConnectionId = m_LocalConnection.ConnectionId,
+ ConnectionId = m_LocalConnection != null ? m_LocalConnection.ConnectionId : ServerClientId,
Data = new ArraySegment()
});
- // Inject local disconnect
- m_LocalConnection.IncomingBuffer.Enqueue(new Event
+ if (m_LocalConnection != null)
{
- Type = NetworkEvent.Disconnect,
- Channel = NetworkChannel.Internal,
- ConnectionId = m_LocalConnection.ConnectionId,
- Data = new ArraySegment()
- });
+ // Inject local disconnect
+ m_LocalConnection.IncomingBuffer.Enqueue(new Event
+ {
+ Type = NetworkEvent.Disconnect,
+ Channel = NetworkChannel.Internal,
+ ConnectionId = m_LocalConnection.ConnectionId,
+ Data = new ArraySegment()
+ });
+
+ if (s_Server != null && m_LocalConnection != null)
+ {
+ // Remove the connection
+ s_Server.Transport.m_Clients.Remove(m_LocalConnection.ConnectionId);
+ }
- // Remove the connection
- s_Server.Transport.m_Clients.Remove(m_LocalConnection.ConnectionId);
+ if (m_LocalConnection.ConnectionId == ServerClientId)
+ {
+ s_Server = null;
+ }
- // Remove the local connection
- m_LocalConnection = null;
+ // Remove the local connection
+ m_LocalConnection = null;
+ }
}
// Called by server
@@ -115,6 +126,12 @@ public override void Shutdown()
Data = new ArraySegment()
});
}
+
+ if (m_LocalConnection != null && m_LocalConnection.ConnectionId == ServerClientId)
+ {
+ s_Server = null;
+ }
+
// TODO: Cleanup
}
diff --git a/testproject/Assets/Tests/Manual/HybridScripts.meta b/testproject/Assets/Tests/Manual/HybridScripts.meta
new file mode 100644
index 0000000000..b207e036d7
--- /dev/null
+++ b/testproject/Assets/Tests/Manual/HybridScripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1954bbeed4577d44ab11f794044a28cf
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/testproject/Assets/Tests/Manual/Scripts/RpcQueueManualTests.cs b/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
similarity index 61%
rename from testproject/Assets/Tests/Manual/Scripts/RpcQueueManualTests.cs
rename to testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
index 6deec92028..cf920d57bb 100644
--- a/testproject/Assets/Tests/Manual/Scripts/RpcQueueManualTests.cs
+++ b/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs
@@ -9,7 +9,7 @@ namespace TestProject.ManualTests
///
/// This class is used to verify that the RPC Queue allows for the
/// sending of ClientRpcs to specific clients. It has several "direct"
- /// methods of sending as is defined in the enum ClientRpcDirectTestingModes:
+ /// methods of sending as is defined in the ENUM ClientRpcDirectTestingModes:
/// Single: This will send to a single client at a time
/// Striped: This will send to alternating client pairs at a time
/// Unified: This sends to all clients at the same time
@@ -18,13 +18,21 @@ namespace TestProject.ManualTests
/// During direct testing mode the following is also tested:
/// all clients are updating the server with a continually growing counter
/// the server is updating all clients with a global counter
- /// During all tests the following additional Rpc Tests are performed:
+ /// During all tests the following additional RPC Tests are performed:
/// Send client to server no parameters and then multiple parameters
/// Send server to client no parameters and then multiple parameters
///
public class RpcQueueManualTests : NetworkBehaviour
{
+ public static bool UnitTesting;
+
private const float k_ProgressBarDivisor = 1.0f / 200.0f;
+ [SerializeField]
+ private bool m_RunInTestMode;
+
+ [SerializeField]
+ [Range(1, 10)]
+ private int m_IterationsToRun;
[SerializeField]
private Text m_CounterTextObject;
@@ -35,13 +43,23 @@ public class RpcQueueManualTests : NetworkBehaviour
[SerializeField]
private GameObject m_ConnectionModeButtonParent;
+ [SerializeField]
+ private NetworkManager m_ManualTestNetworkManager;
+
private Dictionary m_ClientSpecificCounters = new Dictionary();
private List m_ClientIds = new List();
private List m_ClientIndices = new List();
+
+ private bool m_BeginTest;
+ private bool m_HasBeenInitialized;
+ private bool m_ContinueToRun;
private bool m_ConnectionEventOccurred;
private bool m_MultiParameterCanSend;
+
+ private int m_MaxGlobalDirectCounter;
+ private int m_TotalIterations;
private int m_MultiParameterIntValue;
private int m_MultiParameterValuesCount;
private int m_MultiParameterNoneCount;
@@ -57,6 +75,7 @@ public class RpcQueueManualTests : NetworkBehaviour
private long m_MultiParameterLongValue;
private ulong m_LocalClientId;
+ private float m_MesageSendDelay;
private float m_MultiParameterFloatValue;
private float m_GlobalCounterDelay;
private float m_DirectGlobalCounterDelay;
@@ -87,9 +106,79 @@ private enum NetworkManagerMode
private ClientRpcParams m_ClientRpcParams;
private ClientRpcParams m_ClientRpcParamsMultiParameter;
+ private ServerRpcParams m_MultiParameterTargets;
+
+
+ public void DisableManualNetworkManager()
+ {
+ if (m_ManualTestNetworkManager)
+ {
+ m_ManualTestNetworkManager.gameObject.SetActive(false);
+ }
+ }
+
+ public bool IsFinishedWithTest()
+ {
+ if (m_RunInTestMode)
+ {
+ return !m_ContinueToRun;
+ }
+ return false;
+ }
+
+ public void BeginTest()
+ {
+ m_BeginTest = true;
+ }
+
+ public void SetTestingMode(bool enabled, int iterationCount)
+ {
+ m_RunInTestMode = enabled;
+ m_IterationsToRun = Mathf.Clamp(iterationCount, 1, 10);
+ }
+
+ public string GetCurrentServerStatusInfo()
+ {
+ return m_ServerUpdateInfo;
+ }
+
+ public string GetCurrentClientStatusInfo()
+ {
+ return m_ClientUpdateInfo;
+ }
private void Start()
{
+ m_ContinueToRun = true;
+ if (!UnitTesting)
+ {
+ m_BeginTest = true;
+ Initialize();
+ m_MaxGlobalDirectCounter = 100;
+ m_MesageSendDelay = 0.20f;
+ }
+ else
+ {
+ m_ClientRpcParams.Send.TargetClientIds = new ulong[] { 0 };
+ m_ClientRpcParamsMultiParameter.Send.TargetClientIds = new ulong[] { 0 };
+ //For unit tests we will only send 10 per update stage
+ m_MaxGlobalDirectCounter = 10;
+ m_BeginTest = false;
+ m_MesageSendDelay = 0.01f;
+
+ var gameObject = GameObject.Find("NetworkManager");
+ if (gameObject != null)
+ {
+ gameObject.SetActive(false);
+ Destroy(gameObject);
+ Debug.Log($"Found scene {nameof(NetworkManager)}, disabled it, and destroyed it.");
+ }
+ }
+ }
+
+ private void Initialize()
+ {
+ m_TotalIterations = 0;
//Start at a smaller resolution until connection mode is selected.
Screen.SetResolution(320, 320, FullScreenMode.Windowed);
if (m_CounterTextObject)
@@ -106,6 +195,7 @@ private void Start()
connectionModeScript.OnNotifyConnectionEventServer += OnNotifyConnectionEventServer;
}
}
+
}
private void OnNotifyConnectionEventServer()
@@ -154,14 +244,18 @@ public void OnCreateServer()
}
///
- /// Handles common and NetworkManager mode specifc initializations
+ /// Handles common and NetworkManager mode specific initializations
///
private void InitializeNetworkManager()
{
m_ClientRpcParams.Send.TargetClientIds = new ulong[] { 0 };
m_ClientRpcParamsMultiParameter.Send.TargetClientIds = new ulong[] { 0 };
+
m_ClientRpcDirectTestingMode = ClientRpcDirectTestingModes.Single;
- m_ConnectionModeButtonParent.SetActive(false);
+ if (m_ConnectionModeButtonParent)
+ {
+ m_ConnectionModeButtonParent.SetActive(false);
+ }
m_MultiParameterCanSend = true;
m_GlobalDirectScale = 2;
@@ -176,9 +270,9 @@ private void InitializeNetworkManager()
{
case NetworkManagerMode.Client:
{
- if (!m_ConnectionEventOccurred)
+ if (!m_ConnectionEventOccurred && !UnitTesting)
{
- NetworkManager.Singleton.StartClient();
+ NetworkManager.StartClient();
}
m_ServerRpcParams.Send.UpdateStage = NetworkUpdateStage.Update;
Screen.SetResolution(800, 80, FullScreenMode.Windowed);
@@ -186,9 +280,9 @@ private void InitializeNetworkManager()
}
case NetworkManagerMode.Host:
{
- if (!m_ConnectionEventOccurred)
+ if (!m_ConnectionEventOccurred && !UnitTesting)
{
- NetworkManager.Singleton.StartHost();
+ NetworkManager.StartHost();
}
m_ClientRpcParams.Send.UpdateStage = NetworkUpdateStage.PreUpdate;
Screen.SetResolution(800, 480, FullScreenMode.Windowed);
@@ -196,9 +290,9 @@ private void InitializeNetworkManager()
}
case NetworkManagerMode.Server:
{
- if (!m_ConnectionEventOccurred)
+ if (!m_ConnectionEventOccurred && !UnitTesting)
{
- NetworkManager.Singleton.StartServer();
+ NetworkManager.StartServer();
}
m_ClientProgressBar.enabled = false;
m_ClientRpcParams.Send.UpdateStage = NetworkUpdateStage.PostLateUpdate;
@@ -208,6 +302,7 @@ private void InitializeNetworkManager()
}
m_RpcPerSecondTimer = Time.realtimeSinceStartup;
+ m_HasBeenInitialized = true;
}
///
@@ -217,12 +312,12 @@ public override void NetworkStart()
{
if (IsServer)
{
- NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback;
- NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnectCallback;
+ NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback;
+ NetworkManager.OnClientDisconnectCallback += OnClientDisconnectCallback;
if (IsHost)
{
- m_ClientSpecificCounters.Add(NetworkManager.Singleton.LocalClientId, 0);
- m_ClientIds.Add(NetworkManager.Singleton.LocalClientId);
+ m_ClientSpecificCounters.Add(NetworkManager.LocalClientId, 0);
+ m_ClientIds.Add(NetworkManager.LocalClientId);
}
}
}
@@ -234,8 +329,8 @@ private void OnDestroy()
{
if (IsServer)
{
- NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback;
- NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientDisconnectCallback;
+ NetworkManager.OnClientConnectedCallback -= OnClientConnectedCallback;
+ NetworkManager.OnClientDisconnectCallback -= OnClientDisconnectCallback;
}
}
@@ -264,7 +359,7 @@ private void OnClientConnectedCallback(ulong clientId)
if (IsServer)
{
//Exclude the server local id if only a server
- if (!IsHost && clientId == NetworkManager.Singleton.LocalClientId)
+ if (!IsHost && clientId == NetworkManager.LocalClientId)
{
return;
}
@@ -284,80 +379,101 @@ private void OnClientConnectedCallback(ulong clientId)
///
private void Update()
{
- if (NetworkManager.Singleton && NetworkManager.Singleton.IsListening)
+ if (NetworkManager != null && NetworkManager.IsListening && ((IsServer && NetworkManager.ConnectedClientsList.Count > 1) || IsClient) && m_ContinueToRun && m_BeginTest)
{
- if (IsServer)
+ if (UnitTesting && !m_HasBeenInitialized)
{
- if (m_ClientSpecificCounters.Count > 0)
+ if (IsClient)
{
- if (m_GlobalCounterDelay < Time.realtimeSinceStartup)
- {
- m_GlobalCounterDelay = Time.realtimeSinceStartup + 0.200f;
- m_GlobalCounter++;
- OnSendGlobalCounterClientRpc(m_GlobalCounter);
- m_RpcMessagesSent++;
- }
+ OnCreateClient();
+ }
+ else
+ {
+ OnCreateHost();
+ }
+ return;
+ }
- if (m_DirectGlobalCounterDelay < Time.realtimeSinceStartup)
+ if (m_RunInTestMode && m_IterationsToRun <= m_TotalIterations)
+ {
+ m_ContinueToRun = false;
+ }
+ else
+ {
+ if (IsServer)
+ {
+ if (m_ClientSpecificCounters.Count > 0)
{
- switch (m_ClientRpcDirectTestingMode)
+ if (m_GlobalCounterDelay < Time.realtimeSinceStartup)
{
- case ClientRpcDirectTestingModes.Single:
- {
- SingleDirectUpdate();
- break;
- }
- case ClientRpcDirectTestingModes.Striped:
- {
- StripedDirectUpdate();
- break;
- }
- case ClientRpcDirectTestingModes.Unified:
- {
- UnifiedDirectUpdate();
- break;
- }
+ m_GlobalCounterDelay = Time.realtimeSinceStartup + 0.200f;
+ m_GlobalCounter++;
+ OnSendGlobalCounterClientRpc(m_GlobalCounter);
+ m_RpcMessagesSent++;
+ }
+
+ if (m_DirectGlobalCounterDelay < Time.realtimeSinceStartup)
+ {
+ switch (m_ClientRpcDirectTestingMode)
+ {
+ case ClientRpcDirectTestingModes.Single:
+ {
+ SingleDirectUpdate();
+ break;
+ }
+ case ClientRpcDirectTestingModes.Striped:
+ {
+ StripedDirectUpdate();
+ break;
+ }
+ case ClientRpcDirectTestingModes.Unified:
+ {
+ UnifiedDirectUpdate();
+ break;
+ }
+ }
+ m_RpcMessagesSent++;
+ m_DirectGlobalCounterDelay = Time.realtimeSinceStartup + m_GlobalDirectFrequency;
}
- m_RpcMessagesSent++;
- m_DirectGlobalCounterDelay = Time.realtimeSinceStartup + m_GlobalDirectFrequency;
}
}
- }
- //Hosts and Clients execute this
- if (IsHost || IsClient)
- {
- if (m_LocalCounterDelay < Time.realtimeSinceStartup)
+ //Hosts and Clients execute this
+ if (IsHost || IsClient)
{
- m_LocalCounterDelay = Time.realtimeSinceStartup + 0.25f;
- m_LocalClientCounter++;
- OnSendCounterServerRpc(m_LocalClientCounter, m_ServerRpcParams);
- m_RpcMessagesSent++;
- }
- else if (m_LocalMultiDelay < Time.realtimeSinceStartup)
- {
- m_LocalMultiDelay = Time.realtimeSinceStartup + 0.325f;
- if (m_MultiParameterCanSend)
+ if (m_LocalCounterDelay < Time.realtimeSinceStartup)
{
- m_MultiParameterCanSend = false;
- //Multi Parameters
- OnSendMultiParametersServerRpc(m_MultiParameterIntValue, m_MultiParameterFloatValue, m_MultiParameterLongValue, m_ServerRpcParams);
+ m_LocalCounterDelay = Time.realtimeSinceStartup + m_MesageSendDelay + 0.01f;
+ m_LocalClientCounter++;
+
+ OnSendCounterServerRpc(m_LocalClientCounter, NetworkManager.LocalClientId, m_ServerRpcParams);
m_RpcMessagesSent++;
}
- else
+ else if (m_LocalMultiDelay < Time.realtimeSinceStartup)
{
- m_MultiParameterCanSend = true;
- OnSendNoParametersServerRpc(m_ServerRpcParams);
- m_RpcMessagesSent++;
+ m_LocalMultiDelay = Time.realtimeSinceStartup + m_MesageSendDelay + 0.015f;
+ if (m_MultiParameterCanSend)
+ {
+ m_MultiParameterCanSend = false;
+ //Multi Parameters
+ OnSendMultiParametersServerRpc(m_MultiParameterIntValue, m_MultiParameterFloatValue, m_MultiParameterLongValue, m_ServerRpcParams);
+ m_RpcMessagesSent++;
+ }
+ else
+ {
+ m_MultiParameterCanSend = true;
+ OnSendNoParametersServerRpc(m_ServerRpcParams);
+ m_RpcMessagesSent++;
+ }
}
}
- }
- if (Time.realtimeSinceStartup - m_RpcPerSecondTimer > 1.0f)
- {
- m_RpcPerSecondTimer = Time.realtimeSinceStartup;
- m_RpcPerSecond = m_RpcMessagesSent;
- m_RpcMessagesSent = 0;
+ if (Time.realtimeSinceStartup - m_RpcPerSecondTimer > 1.0f)
+ {
+ m_RpcPerSecondTimer = Time.realtimeSinceStartup;
+ m_RpcPerSecond = m_RpcMessagesSent;
+ m_RpcMessagesSent = 0;
+ }
}
}
}
@@ -388,6 +504,10 @@ private void SelectNextDirectUpdateMethod()
case ClientRpcDirectTestingModes.Unified:
{
m_ClientRpcDirectTestingMode = ClientRpcDirectTestingModes.Single;
+ if (m_RunInTestMode)
+ {
+ m_TotalIterations++;
+ }
break;
}
}
@@ -399,7 +519,7 @@ private void SelectNextDirectUpdateMethod()
///
private void SingleDirectUpdate()
{
- if (m_GlobalDirectCounter == 100)
+ if (m_GlobalDirectCounter == m_MaxGlobalDirectCounter)
{
m_GlobalDirectCurrentClientIdIndex++;
if (m_GlobalDirectCurrentClientIdIndex >= m_ClientIds.Count)
@@ -418,9 +538,10 @@ private void SingleDirectUpdate()
m_ClientRpcParams.Send.TargetClientIds = m_ClientIndices.ToArray();
- m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, 100);
+ m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, m_MaxGlobalDirectCounter);
OnSendDirectCounterClientRpc(m_GlobalDirectCounter, m_ClientRpcParams);
+ m_ServerDirectTotalRpcCount++;
}
///
@@ -429,7 +550,7 @@ private void SingleDirectUpdate()
///
private void StripedDirectUpdate()
{
- if (m_GlobalDirectCounter == 100)
+ if (m_GlobalDirectCounter == m_MaxGlobalDirectCounter)
{
m_GlobalDirectCurrentClientIdIndex++;
if (m_GlobalDirectCurrentClientIdIndex >= m_ClientIds.Count)
@@ -450,9 +571,10 @@ private void StripedDirectUpdate()
}
m_ClientRpcParams.Send.TargetClientIds = m_ClientIndices.ToArray();
- m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, 100);
+ m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, m_MaxGlobalDirectCounter);
OnSendDirectCounterClientRpc(m_GlobalDirectCounter, m_ClientRpcParams);
+ m_ServerDirectTotalRpcCount += m_ClientIndices.Count;
}
///
@@ -461,16 +583,16 @@ private void StripedDirectUpdate()
///
private void UnifiedDirectUpdate()
{
- if (m_GlobalDirectCounter == 100)
+ if (m_GlobalDirectCounter == m_MaxGlobalDirectCounter)
{
SelectNextDirectUpdateMethod();
return;
}
m_ClientRpcParams.Send.TargetClientIds = m_ClientIds.ToArray();
- m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, 100);
-
+ m_GlobalDirectCounter = Mathf.Clamp(m_GlobalDirectCounter += m_GlobalDirectScale, 0, m_MaxGlobalDirectCounter);
OnSendDirectCounterClientRpc(m_GlobalDirectCounter, m_ClientRpcParams);
+ m_ServerDirectTotalRpcCount += m_ClientIds.Count;
}
///
@@ -480,16 +602,19 @@ private void UnifiedDirectUpdate()
/// the client side counter
///
[ServerRpc(RequireOwnership = false)]
- private void OnSendCounterServerRpc(int counter, ServerRpcParams parameters = default)
+ private void OnSendCounterServerRpc(int counter, ulong clientId, ServerRpcParams parameters = default)
{
//This is just for debug purposes so I can trap for "non-local" clients
- if (IsHost && parameters.Receive.SenderClientId == 0)
+ if (m_ClientSpecificCounters.ContainsKey(parameters.Receive.SenderClientId))
{
- m_ClientSpecificCounters[parameters.Receive.SenderClientId] = counter;
- }
- else if (m_ClientSpecificCounters.ContainsKey(parameters.Receive.SenderClientId))
- {
- m_ClientSpecificCounters[parameters.Receive.SenderClientId] = counter;
+ if(m_ClientSpecificCounters[parameters.Receive.SenderClientId] < counter)
+ {
+ m_ClientSpecificCounters[parameters.Receive.SenderClientId] = counter;
+ }
+ else
+ {
+ Debug.LogWarning($"Client counter was sent {counter} value but it already was at a value of {m_ClientSpecificCounters[parameters.Receive.SenderClientId]}");
+ }
}
}
@@ -515,7 +640,7 @@ private void OnSendNoParametersServerRpc(ServerRpcParams parameters = default)
private void OnSendMultiParametersServerRpc(int count, float floatValue, long longValue, ServerRpcParams parameters = default)
{
m_ClientRpcParamsMultiParameter.Send.TargetClientIds[0] = parameters.Receive.SenderClientId;
- m_ClientRpcParamsMultiParameter.Send.UpdateStage = NetworkUpdateStage.EarlyUpdate;
+ m_ClientRpcParamsMultiParameter.Send.UpdateStage = NetworkUpdateStage.EarlyUpdate;
OnSendMultiParametersClientRpc(count, floatValue, longValue, m_ClientRpcParamsMultiParameter);
}
@@ -533,7 +658,7 @@ private void OnSendNoParametersClientRpc(ClientRpcParams parameters = default)
///
/// [Tests] Server to Client
- /// Sends multiple parameters to the server
+ /// Sends multiple parameters to the client
///
///
[ClientRpc]
@@ -578,6 +703,7 @@ private void OnSendGlobalCounterClientRpc(int counter)
private void OnSendDirectCounterClientRpc(int counter, ClientRpcParams parameters = default)
{
m_GlobalDirectCounter = counter;
+ m_ClientDirectTotalRpcCount++;
}
///
@@ -585,72 +711,84 @@ private void OnSendDirectCounterClientRpc(int counter, ClientRpcParams parameter
///
private void OnGUI()
{
- if (m_CounterTextObject)
+ if (IsServer && !IsHost || (IsHost && !UnitTesting))
{
- if (IsServer)
- {
- UpdateServerInfo();
- }
- else
- {
- UpdateClientInfo();
- }
+ UpdateServerInfo();
+ }
+ else if (IsHost && UnitTesting)
+ {
+ UpdateServerInfo();
+ UpdateClientInfo();
+ }
+ else
+ {
+ UpdateClientInfo();
}
}
+ private string m_ClientUpdateInfo;
+ private int m_ClientDirectTotalRpcCount;
+
///
/// Update the client text info and progress bar
///
private void UpdateClientInfo()
{
- if (m_LocalClientId == 0 && NetworkManager.Singleton && NetworkManager.Singleton.IsListening)
+ if (m_LocalClientId == 0 && NetworkManager && NetworkManager.IsListening)
{
- m_LocalClientId = NetworkManager.Singleton.LocalClientId;
+ m_LocalClientId = NetworkManager.LocalClientId;
}
+ m_ClientUpdateInfo = $"Client-ID [{m_LocalClientId}] Broadcast Rpcs Received: {m_GlobalCounter - m_GlobalCounterOffset} | Direct Rpcs Received: {(UnitTesting ? m_ClientDirectTotalRpcCount : m_GlobalDirectCounter)} \n";
+ m_ClientUpdateInfo += $"{nameof(m_MultiParameterValuesCount)} : {m_MultiParameterValuesCount} | {nameof(m_MultiParameterNoneCount)} : {m_MultiParameterNoneCount}";
- m_CounterTextObject.text = $"Client-ID [{m_LocalClientId}] Broadcast Rpcs Received: {m_GlobalCounter - m_GlobalCounterOffset} | Direct Rpcs Received: {m_GlobalDirectCounter} \n";
- m_CounterTextObject.text += $"{nameof(m_MultiParameterValuesCount)} : {m_MultiParameterValuesCount} | {nameof(m_MultiParameterNoneCount)} : {m_MultiParameterNoneCount}";
-
- if (m_ClientProgressBar)
+ if (!UnitTesting)
{
- m_ClientProgressBar.fillAmount = Mathf.Clamp((2.0f * (float)m_GlobalDirectCounter) * k_ProgressBarDivisor, 0.01f, 1.0f);
+ m_CounterTextObject.text = m_ClientUpdateInfo;
+ if (m_ClientProgressBar)
+ {
+ m_ClientProgressBar.fillAmount = Mathf.Clamp((2.0f * (float)m_GlobalDirectCounter) * k_ProgressBarDivisor, 0.01f, 1.0f);
+ }
}
}
+ private string m_ServerUpdateInfo;
+ private int m_ServerDirectTotalRpcCount;
///
/// Updates the server text info and host progress bar
///
private void UpdateServerInfo()
{
- string updatedCounters = string.Empty;
+ m_ServerUpdateInfo = string.Empty;
foreach (var entry in m_ClientSpecificCounters)
{
- if (entry.Key == 0 && IsHost)
+ if (entry.Key == NetworkManager.LocalClientId && IsHost)
{
- updatedCounters += $"Client-ID [{entry.Key}] Client to Server Rpcs Received: {entry.Value} | Broadcast Rpcs Sent:{m_GlobalCounter} -- Direct Rpcs Sent:{m_GlobalDirectCounter}\n";
- updatedCounters += $"{nameof(m_MultiParameterValuesCount)} : {m_MultiParameterValuesCount} | {nameof(m_MultiParameterNoneCount)} : {m_MultiParameterNoneCount}\n";
- updatedCounters += $"{nameof(m_RpcPerSecond)} : {m_RpcPerSecond}\n ";
+ m_ServerUpdateInfo += $"Client-ID [{entry.Key}] Client to Server Rpcs Received: {entry.Value} | Broadcast Rpcs Sent:{m_GlobalCounter} -- Direct Rpcs Sent:{(UnitTesting ? m_ServerDirectTotalRpcCount : m_GlobalDirectCounter)}\n";
+ m_ServerUpdateInfo += $"{nameof(m_MultiParameterValuesCount)} : {m_MultiParameterValuesCount} | {nameof(m_MultiParameterNoneCount)} : {m_MultiParameterNoneCount}\n";
+ m_ServerUpdateInfo += $"{nameof(m_RpcPerSecond)} : {m_RpcPerSecond}\n ";
}
else
{
- updatedCounters += $"Client-ID [{entry.Key}] Client to Server Rpcs Received: {entry.Value}\n";
+ m_ServerUpdateInfo += $"Client-ID [{entry.Key}] Client to Server Rpcs Received: {entry.Value}\n";
}
}
- updatedCounters += $"{nameof(m_ClientRpcDirectTestingMode)} : {m_ClientRpcDirectTestingMode}";
+ m_ServerUpdateInfo += $"{nameof(m_ClientRpcDirectTestingMode)} : {m_ClientRpcDirectTestingMode}";
- if (IsHost)
+ if (!UnitTesting)
{
- if (m_GlobalDirectCurrentClientIdIndex < m_ClientIds.Count)
+ if (IsHost)
{
- if (m_ClientProgressBar && m_ClientIndices.Contains(NetworkManager.Singleton.LocalClientId))
+ if (m_GlobalDirectCurrentClientIdIndex < m_ClientIds.Count)
{
- m_ClientProgressBar.fillAmount = Mathf.Clamp((2.0f * (float)m_GlobalDirectCounter) * k_ProgressBarDivisor, 0.01f, 1.0f);
+ if (m_ClientProgressBar && m_ClientIndices.Contains(NetworkManager.LocalClientId))
+ {
+ m_ClientProgressBar.fillAmount = Mathf.Clamp((2.0f * (float)m_GlobalDirectCounter) * k_ProgressBarDivisor, 0.01f, 1.0f);
+ }
}
}
+ m_CounterTextObject.text = m_ServerUpdateInfo;
}
-
- m_CounterTextObject.text = updatedCounters;
}
}
}
diff --git a/testproject/Assets/Tests/Manual/Scripts/RpcQueueManualTests.cs.meta b/testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs.meta
similarity index 100%
rename from testproject/Assets/Tests/Manual/Scripts/RpcQueueManualTests.cs.meta
rename to testproject/Assets/Tests/Manual/HybridScripts/RpcQueueManualTests.cs.meta
diff --git a/testproject/Assets/Tests/Manual/RpcTesting/RpcTesting.unity b/testproject/Assets/Tests/Manual/RpcTesting/RpcTesting.unity
index 73a4eb47ed..8abf854678 100644
--- a/testproject/Assets/Tests/Manual/RpcTesting/RpcTesting.unity
+++ b/testproject/Assets/Tests/Manual/RpcTesting/RpcTesting.unity
@@ -758,7 +758,7 @@ GameObject:
- component: {fileID: 1207168974}
- component: {fileID: 1207168973}
m_Layer: 5
- m_Name: ClientRpcTestsCanvas
+ m_Name: RpcTestsCanvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -875,9 +875,12 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 47f41f8e19d061b49866be44887f53ee, type: 3}
m_Name:
m_EditorClassIdentifier:
+ m_RunInTestMode: 1
+ m_IterationsToRun: 5
m_CounterTextObject: {fileID: 1859881229}
m_ClientProgressBar: {fileID: 521221618}
m_ConnectionModeButtonParent: {fileID: 1705962118}
+ m_ManualTestNetworkManager: {fileID: 0}
--- !u!1 &1544159781
GameObject:
m_ObjectHideFlags: 0
diff --git a/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs b/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs
new file mode 100644
index 0000000000..bb59595813
--- /dev/null
+++ b/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs
@@ -0,0 +1,162 @@
+using System.Collections;
+using System.Collections.Generic;
+using NUnit.Framework;
+using UnityEngine;
+using UnityEngine.TestTools;
+using TestProject.ManualTests;
+using MLAPI.RuntimeTests;
+using MLAPI;
+using Debug = UnityEngine.Debug;
+
+namespace TestProject.RuntimeTests
+{
+ public class RPCTestsAutomated
+ {
+ private bool m_TimedOut;
+
+ ///
+ /// Default Mode (Batched RPCs Enabled)
+ ///
+ ///
+ [UnityTest]
+ public IEnumerator ManualRpcTestsAutomated()
+ {
+ return AutomatedRpcTestsHandler(9);
+ }
+
+ ///
+ /// Same test with Batched RPC turned off
+ ///
+ ///
+ [UnityTest]
+ public IEnumerator ManualRpcTestsAutomatedNoBatching()
+ {
+ return AutomatedRpcTestsHandler(3, false);
+ }
+
+
+ ///
+ /// This just helps to simplify any further tests that can leverage from
+ /// the RpcQueueManualTests' wide array of RPC testing under different
+ /// conditions.
+ /// Currently this allows for the adjustment of client count and whether
+ /// RPC Batching is enabled or not.
+ ///
+ ///
+ ///
+ ///
+ private IEnumerator AutomatedRpcTestsHandler(int numClients, bool useBatching = true)
+ {
+ // Set RpcQueueManualTests into unit testing mode
+ RpcQueueManualTests.UnitTesting = true;
+
+ // Create Host and (numClients) clients
+ Assert.True(MultiInstanceHelpers.Create(numClients, out NetworkManager server, out NetworkManager[] clients));
+
+ // Create a default player GameObject to use
+ var playerPrefab = new GameObject("Player");
+ var networkObject = playerPrefab.AddComponent();
+
+ // Add our RpcQueueManualTests component
+ playerPrefab.AddComponent();
+
+ // Make it a prefab
+ MultiInstanceHelpers.MakeNetworkedObjectTestPrefab(networkObject);
+
+ // Set the player prefab
+ server.NetworkConfig.PlayerPrefab = playerPrefab;
+
+
+ // Set all of the client's player prefab
+ for (int i = 0; i < clients.Length; i++)
+ {
+ clients[i].NetworkConfig.PlayerPrefab = playerPrefab;
+ }
+
+ // Start the instances
+ if (!MultiInstanceHelpers.Start(true, server, clients))
+ {
+ Debug.LogError("Failed to start instances");
+ Assert.Fail("Failed to start instances");
+ }
+
+ // Set the Rpc Batch sending mode
+ server.RpcQueueContainer.EnableBatchedRpcs(useBatching);
+
+ for (int i = 0; i < clients.Length; i++)
+ {
+ clients[i].RpcQueueContainer.EnableBatchedRpcs(useBatching);
+ }
+
+ // [Client-Side] Wait for a connection to the server
+ yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients));
+
+ // [Host-Side] Check to make sure all clients are connected
+ yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clients.Length + 1));
+
+ // [Host-Side] Get the Host owned instance of the RpcQueueManualTests
+ var serverClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper();
+ yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), server, serverClientPlayerResult));
+
+ var serverRpcTests = serverClientPlayerResult.Result.GetComponent();
+ Assert.IsNotNull(serverRpcTests);
+
+ // [Host-Side] Set the (unit) testing mode
+ serverRpcTests.SetTestingMode(true, 1);
+
+ // [Client-Side] Get all of the RpcQueueManualTests instances relative to each client
+ var clientRpcQueueManualTestInstsances = new List();
+ foreach (var client in clients)
+ {
+ var clientClientPlayerResult = new MultiInstanceHelpers.CoroutineResultWrapper();
+ yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.GetNetworkObjectByRepresentation((x => x.IsPlayerObject && x.OwnerClientId == clients[0].LocalClientId), client, clientClientPlayerResult));
+ var clientRpcTests = clientClientPlayerResult.Result.GetComponent();
+ Assert.IsNotNull(clientRpcTests);
+ clientRpcQueueManualTestInstsances.Add(clientRpcTests);
+ }
+
+ // [Client-Side] Set the (unit) testing mode for each client
+ foreach (var rpcClientSideTest in clientRpcQueueManualTestInstsances)
+ {
+ rpcClientSideTest.SetTestingMode(true, 1);
+ }
+
+ // [Host-Side] Begin testing on the host
+ serverRpcTests.BeginTest();
+
+ // [Client-Side] Begin testing on each client
+ foreach (var rpcClientSideTest in clientRpcQueueManualTestInstsances)
+ {
+ rpcClientSideTest.BeginTest();
+ }
+
+ // Wait for the all of the tests to finish
+ var timeOut = Time.realtimeSinceStartup + 5;
+ while (!serverRpcTests.IsFinishedWithTest())
+ {
+ yield return new WaitForSeconds(0.01f);
+ if (timeOut < Time.realtimeSinceStartup)
+ {
+ m_TimedOut = true;
+ break;
+ }
+ }
+
+ // Verify we didn't time out (i.e. all tests ran and finished)
+ Assert.IsFalse(m_TimedOut);
+
+ // Log the output for visual confirmation (Acceptance Test for this test) that all Rpc test types (tracked by counters) executed multiple times
+ Debug.Log("Final Host-Server Status Info:");
+ Debug.Log(serverRpcTests.GetCurrentServerStatusInfo());
+
+ foreach (var rpcClientSideTest in clientRpcQueueManualTestInstsances)
+ {
+ Debug.Log($"Final Client {rpcClientSideTest.NetworkManager.LocalClientId} Status Info:");
+ Debug.Log(rpcClientSideTest.GetCurrentClientStatusInfo());
+ }
+
+ // Shutdown and clean up both of our NetworkManager instances
+ MultiInstanceHelpers.ShutdownAndClean();
+ }
+ }
+}
diff --git a/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs.meta b/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs.meta
new file mode 100644
index 0000000000..9800bda42a
--- /dev/null
+++ b/testproject/Assets/Tests/Runtime/RpcTestsAutomated.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b0cad0e6495da2e4c8dc8541f7850e6f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/testproject/Assets/Tests/Runtime/testproject.runtimetests.asmdef b/testproject/Assets/Tests/Runtime/testproject.runtimetests.asmdef
index 962ebf0b4c..2aa7afc6f7 100644
--- a/testproject/Assets/Tests/Runtime/testproject.runtimetests.asmdef
+++ b/testproject/Assets/Tests/Runtime/testproject.runtimetests.asmdef
@@ -1,11 +1,11 @@
{
"name": "TestProject.RuntimeTests",
"references": [
- "Unity.Multiplayer.MLAPI.Runtime"
+ "Unity.Multiplayer.MLAPI.Runtime",
+ "Unity.Multiplayer.MLAPI.RuntimeTests",
+ "TestProject.ManualTests"
],
"optionalUnityReferences": [
"TestAssemblies"
- ],
- "includePlatforms": [],
- "excludePlatforms": []
+ ]
}
\ No newline at end of file