using System; using UnityEngine; using Cysharp.Threading.Tasks; using System.Threading; using Lights; public class EndGameConditionChecker : IDisposable { public event Action OnEndGameCondition; private bool _isDisposed = false; private float startTime; private float endTime; public float TimeRest => limitedByTime ? endTime - Time.time : -1; private bool limitedByTime; private CancellationTokenSource _cts; private WeaponModel weaponModel; private Health playerHealth; public EndGameConditionChecker(WeaponModel weaponModel, Health playerHealth, int sessionTimeMinutes = 0) { if (weaponModel == null) throw new ArgumentNullException("WeaponModel is null"); if (playerHealth == null) throw new ArgumentNullException("PlayerHealth is null"); this.weaponModel = weaponModel; this.playerHealth = playerHealth; weaponModel.OnNoAmmo += NoAmmoHandler; playerHealth.Died += PlayerDiedHandler; limitedByTime = sessionTimeMinutes > 0; if (limitedByTime) { startTime = Time.time; endTime = startTime + sessionTimeMinutes * 60; _cts = new CancellationTokenSource(); CheckTimeout(_cts).Forget(); } } public void Dispose() { if (_isDisposed) return; _isDisposed = true; _cts?.Cancel(); _cts?.Dispose(); _cts = null; weaponModel.OnNoAmmo -= NoAmmoHandler; playerHealth.Died -= PlayerDiedHandler; weaponModel = null; playerHealth = null; } private void PlayerDiedHandler(Vector3 obj) => TerminateSession(EndgameReason.Death); private void NoAmmoHandler() => TerminateSession(EndgameReason.NoAmmo); private void TerminateSession(EndgameReason reason) { if (_isDisposed) return; Dispose(); OnEndGameCondition?.Invoke(reason); } private async UniTaskVoid CheckTimeout(CancellationTokenSource cts) { while (!cts.IsCancellationRequested) { await UniTask.Delay(1000, cancellationToken: cts.Token); // Проверяем после задержки, не отменена ли операция if (cts.IsCancellationRequested) break; if (TimeRest <= 0) { TerminateSession(EndgameReason.Timeout); break; } } Debug.Log("Конец проверки по времени"); } public enum EndgameReason { Timeout, Death, NoAmmo } }