From 3650a4745196cacd88dde93af755f56915ea554b Mon Sep 17 00:00:00 2001 From: Kitty Draper Date: Tue, 23 Aug 2022 17:50:15 -0500 Subject: [PATCH 1/2] fix: Client RPCs always reporting all RPCs as going to all clients, even when limited by ClientRpcParams --- .../Runtime/Core/NetworkBehaviour.cs | 42 +++++++++-- .../Runtime/Metrics/RpcTestComponent.cs | 2 +- .../Tests/Runtime/Metrics/RpcMetricsTests.cs | 72 ++++++++++++++++--- 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs index 6f96f03697..05637042e5 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs @@ -235,14 +235,42 @@ internal void __endSendClientRpc(ref FastBufferWriter bufferWriter, uint rpcMeth #if DEVELOPMENT_BUILD || UNITY_EDITOR if (NetworkManager.__rpc_name_table.TryGetValue(rpcMethodId, out var rpcMethodName)) { - foreach (var client in NetworkManager.ConnectedClients) + if (clientRpcParams.Send.TargetClientIds != null) { - NetworkManager.NetworkMetrics.TrackRpcSent( - client.Key, - NetworkObject, - rpcMethodName, - __getTypeName(), - rpcWriteSize); + foreach (var targetClientId in clientRpcParams.Send.TargetClientIds) + { + NetworkManager.NetworkMetrics.TrackRpcSent( + targetClientId, + NetworkObject, + rpcMethodName, + __getTypeName(), + rpcWriteSize); + } + } + else if (clientRpcParams.Send.TargetClientIdsNativeArray != null) + { + foreach (var targetClientId in clientRpcParams.Send.TargetClientIdsNativeArray) + { + NetworkManager.NetworkMetrics.TrackRpcSent( + targetClientId, + NetworkObject, + rpcMethodName, + __getTypeName(), + rpcWriteSize); + } + } + else + { + var observerEnumerator = NetworkObject.Observers.GetEnumerator(); + while (observerEnumerator.MoveNext()) + { + NetworkManager.NetworkMetrics.TrackRpcSent( + observerEnumerator.Current, + NetworkObject, + rpcMethodName, + __getTypeName(), + rpcWriteSize); + } } } #endif diff --git a/com.unity.netcode.gameobjects/TestHelpers/Runtime/Metrics/RpcTestComponent.cs b/com.unity.netcode.gameobjects/TestHelpers/Runtime/Metrics/RpcTestComponent.cs index 354a801126..158f5d3c42 100644 --- a/com.unity.netcode.gameobjects/TestHelpers/Runtime/Metrics/RpcTestComponent.cs +++ b/com.unity.netcode.gameobjects/TestHelpers/Runtime/Metrics/RpcTestComponent.cs @@ -14,7 +14,7 @@ public void MyServerRpc() } [ClientRpc] - public void MyClientRpc() + public void MyClientRpc(ClientRpcParams rpcParams = default) { OnClientRpcAction?.Invoke(); } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/RpcMetricsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/RpcMetricsTests.cs index 0d802ce156..be68374c1a 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/RpcMetricsTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Metrics/RpcMetricsTests.cs @@ -2,13 +2,14 @@ using System.Collections; using System.Linq; using NUnit.Framework; +using Unity.Collections; using Unity.Multiplayer.Tools.MetricTypes; using UnityEngine.TestTools; using Unity.Netcode.TestHelpers.Runtime.Metrics; namespace Unity.Netcode.RuntimeTests.Metrics { - internal class RpcMetricsTests : SingleClientMetricTestBase + internal class RpcMetricsTests : DualClientMetricTestBase { protected override void OnCreatePlayerPrefab() { @@ -17,30 +18,79 @@ protected override void OnCreatePlayerPrefab() } [UnityTest] - public IEnumerator TrackRpcSentMetricOnServer() + public IEnumerator TrackRpcSentMetricOnServerToOnlyOneClientWithArray() { var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][Client.LocalClientId].GetComponent().MyClientRpc(); + m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(new ClientRpcParams + { + Send = new ClientRpcSendParams + { + TargetClientIds = new []{FirstClient.LocalClientId} + } + }); yield return waitForMetricValues.WaitForMetricsReceived(); var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); - Assert.AreEqual(2, serverRpcSentValues.Count); // Server will receive this, since it's host + Assert.AreEqual(1, serverRpcSentValues.Count); + + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); + Assert.AreEqual(FirstClient.LocalClientId, serverRpcSentValues.First().Connection.Id); + } + + [UnityTest] + public IEnumerator TrackRpcSentMetricOnServerToOnlyOneClientWithNativeArray() + { + var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); + + m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(new ClientRpcParams + { + Send = new ClientRpcSendParams + { + TargetClientIdsNativeArray = new NativeArray(new []{FirstClient.LocalClientId}, Allocator.Temp) + } + }); + + yield return waitForMetricValues.WaitForMetricsReceived(); + + var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); + Assert.AreEqual(1, serverRpcSentValues.Count); + + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); + Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); + Assert.AreEqual(FirstClient.LocalClientId, serverRpcSentValues.First().Connection.Id); + } + + [UnityTest] + public IEnumerator TrackRpcSentMetricOnServerToAllClients() + { + var waitForMetricValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcSent); + + m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(); + + yield return waitForMetricValues.WaitForMetricsReceived(); + + var serverRpcSentValues = waitForMetricValues.AssertMetricValuesHaveBeenFound(); + Assert.AreEqual(3, serverRpcSentValues.Count); // Server will receive this, since it's host Assert.That(serverRpcSentValues, Has.All.Matches(x => x.Name == nameof(RpcTestComponent.MyClientRpc))); Assert.That(serverRpcSentValues, Has.All.Matches(x => x.NetworkBehaviourName == nameof(RpcTestComponent))); Assert.That(serverRpcSentValues, Has.All.Matches(x => x.BytesCount != 0)); Assert.Contains(Server.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); - Assert.Contains(Client.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); + Assert.Contains(FirstClient.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); + Assert.Contains(SecondClient.LocalClientId, serverRpcSentValues.Select(x => x.Connection.Id).ToArray()); } [UnityTest] public IEnumerator TrackRpcSentMetricOnClient() { - var waitForClientMetricsValues = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.RpcSent); + var waitForClientMetricsValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.RpcSent); - m_PlayerNetworkObjects[Client.LocalClientId][Client.LocalClientId].GetComponent().MyServerRpc(); + m_PlayerNetworkObjects[FirstClient.LocalClientId][FirstClient.LocalClientId].GetComponent().MyServerRpc(); yield return waitForClientMetricsValues.WaitForMetricsReceived(); @@ -58,7 +108,7 @@ public IEnumerator TrackRpcSentMetricOnClient() public IEnumerator TrackRpcReceivedMetricOnServer() { var waitForServerMetricsValues = new WaitForEventMetricValues(ServerMetrics.Dispatcher, NetworkMetricTypes.RpcReceived); - m_PlayerNetworkObjects[Client.LocalClientId][Client.LocalClientId].GetComponent().MyServerRpc(); + m_PlayerNetworkObjects[FirstClient.LocalClientId][FirstClient.LocalClientId].GetComponent().MyServerRpc(); yield return waitForServerMetricsValues.WaitForMetricsReceived(); @@ -66,7 +116,7 @@ public IEnumerator TrackRpcReceivedMetricOnServer() Assert.AreEqual(1, serverRpcReceivedValues.Count); var rpcReceived = serverRpcReceivedValues.First(); - Assert.AreEqual(Client.LocalClientId, rpcReceived.Connection.Id); + Assert.AreEqual(FirstClient.LocalClientId, rpcReceived.Connection.Id); Assert.AreEqual(nameof(RpcTestComponent.MyServerRpc), rpcReceived.Name); Assert.AreEqual(nameof(RpcTestComponent), rpcReceived.NetworkBehaviourName); Assert.AreNotEqual(0, rpcReceived.BytesCount); @@ -75,9 +125,9 @@ public IEnumerator TrackRpcReceivedMetricOnServer() [UnityTest] public IEnumerator TrackRpcReceivedMetricOnClient() { - var waitForClientMetricsValues = new WaitForEventMetricValues(ClientMetrics.Dispatcher, NetworkMetricTypes.RpcReceived); + var waitForClientMetricsValues = new WaitForEventMetricValues(FirstClientMetrics.Dispatcher, NetworkMetricTypes.RpcReceived); - m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][Client.LocalClientId].GetComponent().MyClientRpc(); + m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][FirstClient.LocalClientId].GetComponent().MyClientRpc(); yield return waitForClientMetricsValues.WaitForMetricsReceived(); From 1855f4363d2b94aff620e0f5a6739a5380d1b227 Mon Sep 17 00:00:00 2001 From: Kitty Draper Date: Tue, 23 Aug 2022 18:13:40 -0500 Subject: [PATCH 2/2] Changelog --- com.unity.netcode.gameobjects/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 627975e120..db57f8eccd 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -7,6 +7,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). +## [Unreleased] + +### Fixed + +- Fixed ClientRpcs always reporting in the profiler view as going to all clients, even when limited to a subset of clients by ClientRpcParams. (#2144) + ## [1.0.1] - 2022-08-23 ### Changed