using System.Globalization; using System.Text; using RebootKit.Engine.Main; using RebootKit.Engine.Network; using RebootKit.Engine.Simulation; using RebootKit.Engine.UI; using UnityEngine; using UnityEngine.UIElements; namespace RebootKit.Engine.Development { public class DebugOverlayView : UIDocumentView { const string k_DebugLabelClassName = "rr__debug-overlay-label"; string m_HeaderText; VisualElement m_RootElement; Label m_Label; readonly StringBuilder m_StringBuilder = new StringBuilder(); // // @MARK: Unity callbacks // void Update() { if (m_RootElement == null) { return; } m_StringBuilder.AppendLine(m_HeaderText); AppendFPSInfo(); AppendNetworkStateInfo(); AppendActorsStateInfo(); m_Label.text = m_StringBuilder.ToString(); m_StringBuilder.Clear(); } void AppendFPSInfo() { Resolution resolution = Screen.currentResolution; m_StringBuilder.Append("fps: "); m_StringBuilder.Append(Mathf.RoundToInt(1.0f / Time.unscaledDeltaTime)); m_StringBuilder.Append(" | dt: "); m_StringBuilder.Append(Time.deltaTime.ToString("F4")); m_StringBuilder.Append("ms | runtime: "); m_StringBuilder.Append(Time.time.ToString("F4")); m_StringBuilder.Append("s | resolution: "); m_StringBuilder.Append(resolution.width); m_StringBuilder.Append("x"); m_StringBuilder.Append(resolution.height); m_StringBuilder.Append("@"); m_StringBuilder.Append(resolution.refreshRateRatio); m_StringBuilder.Append("Hz | IsLittleEndian: "); m_StringBuilder.Append(System.BitConverter.IsLittleEndian ? "true" : "false"); m_StringBuilder.AppendLine(); } void AppendNetworkStateInfo() { NetworkSystem network = RR.Network; if (network == null) { m_StringBuilder.AppendLine("NetworkSystem not initialized"); return; } m_StringBuilder.Append($"IsServer: {RR.IsServer().ToString()}"); m_StringBuilder.Append($" | TickRate: {NetworkSystem.TickRate.IndexValue.ToString()}"); m_StringBuilder.Append($" | IsClient: {RR.IsClient().ToString()}"); m_StringBuilder.Append($" | WorldID: {network.WorldID.ToString()}"); m_StringBuilder.Append($" | Clients: {network.Clients.Count.ToString()}"); m_StringBuilder.Append($" | ReadyClientsCount: {network.GetReadyClientsCount().ToString()}"); m_StringBuilder.Append($" | Last Tick Packets Sent: {network.LastTickPacketsSentCount.ToString()}"); m_StringBuilder.AppendLine(); if (network.TryGetClientState(network.LocalClientID, out NetworkClientState clientState)) { m_StringBuilder.Append($"LocalClientID: {clientState.ClientID.ToString()}"); m_StringBuilder.Append($" | SyncState: {clientState.SyncState.ToString()}"); m_StringBuilder.Append($" | IsReady: {clientState.IsReady.ToString()}"); } else { m_StringBuilder.Append("ClientState not found for LocalClientID: "); m_StringBuilder.Append(network.LocalClientID.ToString()); } m_StringBuilder.AppendLine(); if (network.Manager.Stats != null) { m_StringBuilder.Append("Stats: "); m_StringBuilder.Append($"Send Reliable: {FormatToLargestUnit(network.Manager.Stats.ReliableBytesSentPerSecond)}/s"); m_StringBuilder.Append($" | Send Unreliable: {FormatToLargestUnit(network.Manager.Stats.UnreliableBytesSentPerSecond)}/s"); m_StringBuilder.Append($" | Receive: {FormatToLargestUnit(network.Manager.Stats.BytesReceivedPerSecond)}/s"); m_StringBuilder.Append($" | Ping: {network.Manager.Stats.Ping.ToString()}ms"); m_StringBuilder.AppendLine(); } } string FormatToLargestUnit(double value) { if (value < 1024) { return $"{value:F2} B"; } if (value < 1024 * 1024) { return $"{(value / 1024):F2} KB"; } if (value < 1024 * 1024 * 1024) { return $"{(value / (1024 * 1024)):F2} MB"; } return $"{(value / (1024 * 1024 * 1024)):F2} GB"; } void AppendActorsStateInfo() { NetworkSystem network = RR.Network; if (network == null) { return; } ActorsManager actorsManager = network.Actors; if (actorsManager == null) { m_StringBuilder.Append("ActorsManager not initialized"); return; } m_StringBuilder.Append("InScene Actors Count: "); m_StringBuilder.Append(actorsManager.InSceneActorsCount.ToString()); m_StringBuilder.Append(" | Dynamic Actors Count: "); m_StringBuilder.Append(actorsManager.SpawnedActorsCount.ToString()); m_StringBuilder.Append(" | Total Actors Count: "); m_StringBuilder.Append(actorsManager.TotalActorsCount.ToString()); m_StringBuilder.AppendLine(); } // // @MARK: UIDocumentView // public override VisualElement Build() { if (m_HeaderText == null) { m_HeaderText = $"Toggle Overlay [F3] | RebootKit | game: {Application.productName}, version: {Application.version}"; } m_RootElement = new VisualElement(); m_Label = (Label)LabelBuilder.New("").Build(); m_Label.AddToClassList(k_DebugLabelClassName); m_RootElement.Add(m_Label); return m_RootElement; } } }