using System.Collections.Generic; using UnityEngine; namespace MazeGen { /// /// The single source of truth for "is the maze simulation running right now". /// /// Everything that advances maze state (agent decision timers, fight muster countdowns, /// the level's elapsed-time clock) must tick on rather than /// , so that one pause freezes the whole simulation coherently. /// /// Deliberately does NOT touch : real Unity time has to keep /// flowing while the maze is frozen, because that's what drives the watched-fight playback /// animation and its coroutines. /// /// Pausing is ref-counted by reason string (/) so /// several independent things - three fights breaking out at once, plus an arena playback - /// can each hold the simulation without stomping on each other's resume. The user's own /// pause button is separate () and always wins. /// public static class SimulationClock { private static readonly HashSet _holds = new HashSet(); private static bool _userPaused; private static float _timeScale = 1f; /// The observer's manual pause. Independent of, and additive with, any holds. public static bool UserPaused { get => _userPaused; set => _userPaused = value; } /// Fast-forward / slow-motion multiplier for maze simulation time. public static float TimeScale { get => _timeScale; set => _timeScale = Mathf.Clamp(value, 0.1f, 8f); } public static bool IsPaused => _userPaused || _holds.Count > 0; /// Human-readable list of what's currently holding the simulation (null if nothing is). public static string HoldSummary => _holds.Count == 0 ? null : string.Join(", ", _holds); /// Scaled simulation delta for this frame - zero while paused. public static float DeltaTime => IsPaused ? 0f : Time.deltaTime * _timeScale; public static void PushHold(string reason) => _holds.Add(reason ?? "hold"); public static void PopHold(string reason) => _holds.Remove(reason ?? "hold"); public static bool HasHold(string reason) => _holds.Contains(reason ?? "hold"); /// /// Clears all state. Called from MazeSceneBuilder.Awake because this is static state and /// the editor can be configured to skip domain reload between Play sessions, which would /// otherwise leave a stale pause hold from the previous run holding the new one frozen. /// public static void Reset() { _holds.Clear(); _userPaused = false; _timeScale = 1f; } } }