using System; using UnityEngine; namespace Mirror { /// /// Shows Network messages and bytes sent and received per second. /// /// /// Add this component to the same object as Network Manager. /// [AddComponentMenu("Network/Network Statistics")] [DisallowMultipleComponent] [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-statistics")] public class NetworkStatistics : MonoBehaviour { // update interval double intervalStartTime; // --------------------------------------------------------------------- // CLIENT (public fields for other components to grab statistics) // long bytes to support >2GB [HideInInspector] public int clientIntervalReceivedPackets; [HideInInspector] public long clientIntervalReceivedBytes; [HideInInspector] public int clientIntervalSentPackets; [HideInInspector] public long clientIntervalSentBytes; // results from last interval // long bytes to support >2GB [HideInInspector] public int clientReceivedPacketsPerSecond; [HideInInspector] public long clientReceivedBytesPerSecond; [HideInInspector] public int clientSentPacketsPerSecond; [HideInInspector] public long clientSentBytesPerSecond; // --------------------------------------------------------------------- // SERVER (public fields for other components to grab statistics) // capture interval // long bytes to support >2GB [HideInInspector] public int serverIntervalReceivedPackets; [HideInInspector] public long serverIntervalReceivedBytes; [HideInInspector] public int serverIntervalSentPackets; [HideInInspector] public long serverIntervalSentBytes; // results from last interval // long bytes to support >2GB [HideInInspector] public int serverReceivedPacketsPerSecond; [HideInInspector] public long serverReceivedBytesPerSecond; [HideInInspector] public int serverSentPacketsPerSecond; [HideInInspector] public long serverSentBytesPerSecond; // NetworkManager sets Transport.active in Awake(). // so let's hook into it in Start(). void Start() { // find available transport Transport transport = Transport.active; if (transport != null) { transport.OnClientDataReceived += OnClientReceive; transport.OnClientDataSent += OnClientSend; transport.OnServerDataReceived += OnServerReceive; transport.OnServerDataSent += OnServerSend; } else Debug.LogError($"NetworkStatistics: no available or active Transport found on this platform: {Application.platform}"); } void OnDestroy() { // remove transport hooks Transport transport = Transport.active; if (transport != null) { transport.OnClientDataReceived -= OnClientReceive; transport.OnClientDataSent -= OnClientSend; transport.OnServerDataReceived -= OnServerReceive; transport.OnServerDataSent -= OnServerSend; } } void OnClientReceive(ArraySegment data, int channelId) { ++clientIntervalReceivedPackets; clientIntervalReceivedBytes += data.Count; } void OnClientSend(ArraySegment data, int channelId) { ++clientIntervalSentPackets; clientIntervalSentBytes += data.Count; } void OnServerReceive(int connectionId, ArraySegment data, int channelId) { ++serverIntervalReceivedPackets; serverIntervalReceivedBytes += data.Count; } void OnServerSend(int connectionId, ArraySegment data, int channelId) { ++serverIntervalSentPackets; serverIntervalSentBytes += data.Count; } void Update() { // calculate results every second if (NetworkTime.localTime >= intervalStartTime + 1) { if (NetworkClient.active) UpdateClient(); if (NetworkServer.active) UpdateServer(); intervalStartTime = NetworkTime.localTime; } } void UpdateClient() { clientReceivedPacketsPerSecond = clientIntervalReceivedPackets; clientReceivedBytesPerSecond = clientIntervalReceivedBytes; clientSentPacketsPerSecond = clientIntervalSentPackets; clientSentBytesPerSecond = clientIntervalSentBytes; clientIntervalReceivedPackets = 0; clientIntervalReceivedBytes = 0; clientIntervalSentPackets = 0; clientIntervalSentBytes = 0; } void UpdateServer() { serverReceivedPacketsPerSecond = serverIntervalReceivedPackets; serverReceivedBytesPerSecond = serverIntervalReceivedBytes; serverSentPacketsPerSecond = serverIntervalSentPackets; serverSentBytesPerSecond = serverIntervalSentBytes; serverIntervalReceivedPackets = 0; serverIntervalReceivedBytes = 0; serverIntervalSentPackets = 0; serverIntervalSentBytes = 0; } void OnGUI() { // only show if either server or client active if (NetworkClient.active || NetworkServer.active) { // create main GUI area // 120 is below NetworkManager HUD in all cases. GUILayout.BeginArea(new Rect(10, 120, 215, 300)); // show client / server stats if active if (NetworkClient.active) OnClientGUI(); if (NetworkServer.active) OnServerGUI(); // end of GUI area GUILayout.EndArea(); } } void OnClientGUI() { // background GUILayout.BeginVertical("Box"); GUILayout.Label("Client Statistics"); // sending ("msgs" instead of "packets" to fit larger numbers) GUILayout.Label($"Send: {clientSentPacketsPerSecond} msgs @ {Utils.PrettyBytes(clientSentBytesPerSecond)}/s"); // receiving ("msgs" instead of "packets" to fit larger numbers) GUILayout.Label($"Recv: {clientReceivedPacketsPerSecond} msgs @ {Utils.PrettyBytes(clientReceivedBytesPerSecond)}/s"); // end background GUILayout.EndVertical(); } void OnServerGUI() { // background GUILayout.BeginVertical("Box"); GUILayout.Label("Server Statistics"); // sending ("msgs" instead of "packets" to fit larger numbers) GUILayout.Label($"Send: {serverSentPacketsPerSecond} msgs @ {Utils.PrettyBytes(serverSentBytesPerSecond)}/s"); // receiving ("msgs" instead of "packets" to fit larger numbers) GUILayout.Label($"Recv: {serverReceivedPacketsPerSecond} msgs @ {Utils.PrettyBytes(serverReceivedBytesPerSecond)}/s"); // end background GUILayout.EndVertical(); } } }