using System; using System.Collections.Generic; using UnityEngine; namespace Unity.Netcode.RuntimeTests { /// /// Used in conjunction with the RpcQueueTest to validate: /// - Sending and Receiving pipeline to validate that both sending and receiving pipelines are functioning properly. /// - Usage of the ServerRpcParams.Send.UpdateStage and ClientRpcParams.Send.UpdateStage functionality. /// - Rpcs receive will be invoked at the appropriate NetworkUpdateStage. /// public class RpcPipelineTestComponent : NetworkBehaviour { /// /// Allows the external RPCQueueTest to begin testing or stop it /// public bool PingSelfEnabled; /// /// How many times will we iterate through the various NetworkUpdateStage values? /// (defaults to 2) /// public int MaxIterations = 2; // Start is called before the first frame update private void Start() { m_MaxStagesSent = Enum.GetValues(typeof(NetworkUpdateStage)).Length * MaxIterations; //Start out with this being true (for first sequence) m_ClientReceivedRpc = true; } /// /// Determine if we have iterated over more than our maximum stages we want to test /// /// true or false (did we exceed the max iterations or not?) public bool ExceededMaxIterations() { if (m_StagesSent.Count > m_MaxStagesSent && m_MaxStagesSent > 0) { return true; } return false; } /// /// Returns back whether the test has completed the total number of iterations /// /// public bool IsTestComplete() { if (m_Counter >= MaxIterations) { return true; } return false; } private bool m_ClientReceivedRpc; private int m_Counter = 0; private int m_MaxStagesSent = 0; private ServerRpcParams m_ServerParams; private ClientRpcParams m_ClientParams; private NetworkUpdateStage m_LastUpdateStage; // Update is called once per frame private void Update() { if (NetworkManager.Singleton.IsListening && PingSelfEnabled && m_ClientReceivedRpc) { //Reset this for the next sequence of rpcs m_ClientReceivedRpc = false; //As long as testing isn't completed, keep testing if (!IsTestComplete()) { PingMySelfServerRpc(m_StagesSent.Count, m_ServerParams); } } } private readonly List m_ServerStagesReceived = new List(); private readonly List m_ClientStagesReceived = new List(); private readonly List m_StagesSent = new List(); /// /// Assures all update stages were in alginment with one another /// /// true or false public bool ValidateUpdateStages() { var validated = false; if (m_ServerStagesReceived.Count == m_ClientStagesReceived.Count && m_ClientStagesReceived.Count == m_StagesSent.Count) { for (int i = 0; i < m_StagesSent.Count; i++) { var currentStage = m_StagesSent[i]; if (m_ServerStagesReceived[i] != currentStage) { Debug.Log($"ServerRpc Update Stage ({m_ServerStagesReceived[i]}) is not equal to the current update stage ({currentStage})"); return validated; } if (m_ClientStagesReceived[i] != currentStage) { Debug.Log($"ClientRpc Update Stage ({m_ClientStagesReceived[i]}) is not equal to the current update stage ({currentStage})"); return validated; } } validated = true; } return validated; } /// /// Server side RPC for testing /// /// server rpc parameters [ServerRpc] private void PingMySelfServerRpc(int currentCount, ServerRpcParams parameters = default) { Debug.Log($"{nameof(PingMySelfServerRpc)}: [HostClient][ServerRpc][{currentCount}] invoked."); PingMySelfClientRpc(currentCount, m_ClientParams); } /// /// Client Side RPC called by PingMySelfServerRPC to validate both Client->Server and Server-Client pipeline is working /// /// client rpc parameters [ClientRpc] private void PingMySelfClientRpc(int currentCount, ClientRpcParams parameters = default) { Debug.Log($"{nameof(PingMySelfClientRpc)}: [HostServer][ClientRpc][{currentCount}] invoked. (previous output line should confirm this)"); m_ClientReceivedRpc = true; } } }