| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- using System.Collections.Generic;
- using UnityEngine;
- namespace MazeGen
- {
- /// <summary>
- /// 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 <see cref="DeltaTime"/> rather than
- /// <see cref="Time.deltaTime"/>, so that one pause freezes the whole simulation coherently.
- ///
- /// Deliberately does NOT touch <see cref="Time.timeScale"/>: 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 (<see cref="PushHold"/>/<see cref="PopHold"/>) 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 (<see cref="UserPaused"/>) and always wins.
- /// </summary>
- public static class SimulationClock
- {
- private static readonly HashSet<string> _holds = new HashSet<string>();
- private static bool _userPaused;
- private static float _timeScale = 1f;
- /// <summary>The observer's manual pause. Independent of, and additive with, any holds.</summary>
- public static bool UserPaused
- {
- get => _userPaused;
- set => _userPaused = value;
- }
- /// <summary>Fast-forward / slow-motion multiplier for maze simulation time.</summary>
- public static float TimeScale
- {
- get => _timeScale;
- set => _timeScale = Mathf.Clamp(value, 0.1f, 8f);
- }
- public static bool IsPaused => _userPaused || _holds.Count > 0;
- /// <summary>Human-readable list of what's currently holding the simulation (null if nothing is).</summary>
- public static string HoldSummary => _holds.Count == 0 ? null : string.Join(", ", _holds);
- /// <summary>Scaled simulation delta for this frame - zero while paused.</summary>
- 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");
- /// <summary>
- /// 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.
- /// </summary>
- public static void Reset()
- {
- _holds.Clear();
- _userPaused = false;
- _timeScale = 1f;
- }
- }
- }
|