// =============================================================================== // 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) { // Only display the panel when the game is actually running if (!Application.isPlaying) return; Handles.BeginGUI(); // Calculate center-top position dynamically based on current Scene View size float posX = (sceneView.position.width - PANEL_WIDTH) / 2f; float posY = 15f; Rect panelRect = new Rect(posX, posY, PANEL_WIDTH, PANEL_HEIGHT); // Draw the main background box GUI.Box(panelRect, GUIContent.none, EditorStyles.helpBox); GUILayout.BeginArea(new Rect(posX + 10, posY + 10, PANEL_WIDTH - 20, PANEL_HEIGHT - 20)); // --- 1. HEADER (Title & Current Speed) --- GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel) { richText = true, alignment = TextAnchor.MiddleCenter, fontSize = 13 }; // Format the time scale to show 2 decimal places string currentSpeedText = EditorApplication.isPaused ? "PAUSED" : $"{Time.timeScale:F2}x"; GUILayout.Label($"⏳ TIME LORD | Current: {currentSpeedText}", headerStyle); GUILayout.Space(5); // --- 2. TIME SLIDER (Fine-tune control) --- EditorGUI.BeginChangeCheck(); float newTimeScale = GUILayout.HorizontalSlider(Time.timeScale, 0f, 10f); if (EditorGUI.EndChangeCheck()) { Time.timeScale = newTimeScale; // Auto-resume if adjusting slider while paused if (EditorApplication.isPaused && newTimeScale > 0f) { EditorApplication.isPaused = false; } } GUILayout.Space(5); // --- 3. PRESET SPEED BUTTONS --- GUILayout.BeginHorizontal(); DrawSpeedButton("0.1x", 0.1f); DrawSpeedButton("0.5x", 0.5f); DrawSpeedButton("1x", 1f); DrawSpeedButton("2x", 2f); DrawSpeedButton("5x", 5f); GUILayout.EndHorizontal(); GUILayout.Space(5); // --- 4. PAUSE / RESUME BUTTON --- Color oldBgColor = GUI.backgroundColor; GUI.backgroundColor = EditorApplication.isPaused ? new Color(1f, 0.4f, 0.4f) : new Color(0.9f, 0.9f, 0.9f); string pauseLabel = EditorApplication.isPaused ? "▶ RESUME GAME" : "⏸ PAUSE GAME"; GUIStyle pauseStyle = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold }; if (GUILayout.Button(pauseLabel, pauseStyle, GUILayout.Height(25))) { EditorApplication.isPaused = !EditorApplication.isPaused; } GUI.backgroundColor = oldBgColor; 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) { 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.Height(22))) { 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; } } }