#if UNITY_EDITOR // =============================================================================== // TimeLord - In-Scene Time Manipulation Tool // // Creator: Scove // Last Updated: 2026-03-03 // Version: 2.0 (Sleek UI & Ergonomic Controls) // // Purpose: // Provides a floating, interactive control panel inside the Scene View during // Play Mode. Allows developers to easily manipulate game time (slow motion, // fast forward, or pause) without constantly looking away from the action. // // Key Features: // 1. Floating Dashboard: Clean, unobtrusive UI placed directly in the Scene View. // 2. Dynamic Slider: Drag to fine-tune the time scale smoothly from 0x to 10x. // 3. Smart Highlighting: Active speeds light up (Green), making it easy to read. // 4. Auto-Resume: Clicking a speed preset while paused automatically resumes play. // 5. Visual Pause State: Prominent pause button changes color when active. // // How to Use: // 1. Place this script in an 'Editor' folder. // 2. Hit PLAY in Unity. // 3. Move your mouse to the Scene View and use the top-center Time Lord panel! // =============================================================================== using UnityEditor; using UnityEngine; namespace Editor { [InitializeOnLoad] public class TimeLord { // Panel configuration private const float PANEL_WIDTH = 340f; private const float PANEL_HEIGHT = 105f; static TimeLord() { // Unsubscribe first to prevent double-hooking upon script recompile SceneView.duringSceneGui -= OnSceneGUI; SceneView.duringSceneGui += OnSceneGUI; } private static void OnSceneGUI(SceneView sceneView) { if (!Application.isPlaying) return; Handles.BeginGUI(); float panelWidth = 460f; float panelHeight = 40f; float posX = (sceneView.position.width - panelWidth) / 2f; float posY = 20f; Rect panelRect = new Rect(posX, posY, panelWidth, panelHeight); // Sleek semi-transparent dark background EditorGUI.DrawRect(panelRect, new Color(0.1f, 0.1f, 0.1f, 0.85f)); // Thin accent line at the top EditorGUI.DrawRect(new Rect(posX, posY, panelWidth, 2), new Color(0.3f, 0.7f, 1f, 0.8f)); GUILayout.BeginArea(new Rect(posX + 10, posY + 8, panelWidth - 20, panelHeight - 16)); GUILayout.BeginHorizontal(); // --- 1. HEADER (Current Speed) --- string currentSpeedText = EditorApplication.isPaused ? "PAUSED" : $"{Time.timeScale:F2}x"; GUILayout.Label($"⏳ {currentSpeedText}", new GUIStyle(EditorStyles.boldLabel) { richText = true, fontSize = 13, alignment = TextAnchor.MiddleLeft }, GUILayout.Width(80)); // --- 2. TIME SLIDER (Fine-tune control) --- EditorGUI.BeginChangeCheck(); float newTimeScale = GUILayout.HorizontalSlider(Time.timeScale, 0f, 10f, GUILayout.Width(80), GUILayout.Height(20)); if (EditorGUI.EndChangeCheck()) { Time.timeScale = newTimeScale; if (EditorApplication.isPaused && newTimeScale > 0f) { EditorApplication.isPaused = false; } } GUILayout.Space(15); // --- 3. PRESET SPEED BUTTONS --- DrawSpeedButton("0.5x", 0.5f, 35); DrawSpeedButton("1x", 1f, 30); DrawSpeedButton("2x", 2f, 30); DrawSpeedButton("5x", 5f, 30); GUILayout.FlexibleSpace(); // --- 4. PAUSE / RESUME BUTTON --- Color oldBgColor = GUI.backgroundColor; GUI.backgroundColor = EditorApplication.isPaused ? new Color(1f, 0.4f, 0.4f) : new Color(0.8f, 0.8f, 0.8f); string pauseLabel = EditorApplication.isPaused ? "▶ RESUME" : "⏸ PAUSE"; GUIStyle pauseStyle = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold }; if (GUILayout.Button(pauseLabel, pauseStyle, GUILayout.Width(80), GUILayout.Height(24))) { EditorApplication.isPaused = !EditorApplication.isPaused; } GUI.backgroundColor = oldBgColor; GUILayout.EndHorizontal(); GUILayout.EndArea(); Handles.EndGUI(); } /// /// Draws a preset button that automatically highlights green if it matches the current time scale. /// private static void DrawSpeedButton(string label, float targetSpeed, float width) { Color oldBgColor = GUI.backgroundColor; // Highlight green if this is the active speed AND the game is not paused bool isActive = Mathf.Approximately(Time.timeScale, targetSpeed) && !EditorApplication.isPaused; if (isActive) { GUI.backgroundColor = new Color(0.4f, 1f, 0.4f); // Light Green } if (GUILayout.Button(label, GUILayout.Width(width), GUILayout.Height(24))) { Time.timeScale = targetSpeed; // Auto-resume if the player clicked a speed while paused if (EditorApplication.isPaused) { EditorApplication.isPaused = false; } } // Restore previous color GUI.backgroundColor = oldBgColor; } } } #endif