using UnityEngine; using UnityEngine.UIElements; namespace Hallucinate.UI { public class PerformanceOverlay : MonoBehaviour { private static PerformanceOverlay _instance; private Label _fpsLabel; private UIDocument _uiDocument; private VisualElement _root; private float _deltaTime = 0f; private bool _isVisible = false; public static void SetVisible(bool visible) { if (_instance == null && visible) { var go = new GameObject("PerformanceOverlay"); _instance = go.AddComponent(); DontDestroyOnLoad(go); } if (_instance != null) { _instance._isVisible = visible; if (_instance._root != null) { _instance._root.style.display = visible ? DisplayStyle.Flex : DisplayStyle.None; } } } private void Awake() { _uiDocument = gameObject.AddComponent(); // Use same panel settings as UIManager if possible, or default _uiDocument.panelSettings = Resources.Load("UI/PerformancePanelSettings"); _root = new VisualElement(); _root.style.position = Position.Absolute; _root.style.bottom = 10; _root.style.left = 10; _root.pickingMode = PickingMode.Ignore; _fpsLabel = new Label("0 FPS (0.0ms)"); _fpsLabel.style.color = Color.white; _fpsLabel.style.fontSize = 14; _fpsLabel.style.unityFontStyleAndWeight = FontStyle.Bold; // Shadow effect _fpsLabel.style.textShadow = new TextShadow { offset = new Vector2(1, 1), blurRadius = 1, color = Color.black }; _root.Add(_fpsLabel); _uiDocument.rootVisualElement.Add(_root); _root.style.display = _isVisible ? DisplayStyle.Flex : DisplayStyle.None; } private void Update() { if (!_isVisible) return; _deltaTime += (Time.unscaledDeltaTime - _deltaTime) * 0.1f; float fps = 1.0f / _deltaTime; float ms = _deltaTime * 1000.0f; _fpsLabel.text = $"{Mathf.Ceil(fps)} FPS ({ms:F1}ms)"; // Color coding based on performance if (fps < 30) _fpsLabel.style.color = Color.red; else if (fps < 55) _fpsLabel.style.color = Color.yellow; else _fpsLabel.style.color = Color.green; } } }