using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; namespace DDD { public class TimeManager : Singleton, IManager, IEventHandler { private readonly Dictionary _timeScaleRequests = new(); public float CurrentTimeScale { get; private set; } = 1f; private float _baseFixedDeltaTime; public void PreInit() { _baseFixedDeltaTime = Time.fixedDeltaTime; EventBus.Register(this); } public Task Init() { return Task.CompletedTask; } public void PostInit() { } private void OnDestroy() { EventBus.Unregister(this); #if UNITY_EDITOR Time.fixedDeltaTime = _baseFixedDeltaTime; // 재실행 시 값 복원 (Editor용 안전장치) #endif } protected override void OnApplicationQuit() { base.OnApplicationQuit(); Time.fixedDeltaTime = _baseFixedDeltaTime; } private void UpdateTimeScale() { // 우선순위: 0이 하나라도 있으면 무조건 정지, 그 외엔 최소값 적용 float newTimeScale = 1f; if (_timeScaleRequests.ContainsValue(0f)) { newTimeScale = 0f; } else if (_timeScaleRequests.Count > 0) { newTimeScale = Mathf.Min(1f, Mathf.Min(float.MaxValue, GetMinTimeScale())); } if (Mathf.Approximately(newTimeScale, CurrentTimeScale)) return; CurrentTimeScale = newTimeScale; Time.timeScale = CurrentTimeScale; Time.fixedDeltaTime = _baseFixedDeltaTime * CurrentTimeScale; } private float GetMinTimeScale() => _timeScaleRequests.Values.Prepend(1f).Min(); public bool IsPaused => Mathf.Approximately(CurrentTimeScale, 0f); public void Invoke(TimeScaleChangeEvent evt) { if (evt.NewTimeScale < 1f) { _timeScaleRequests[evt.Requester] = evt.NewTimeScale; } else { _timeScaleRequests.Remove(evt.Requester); } UpdateTimeScale(); } } }