using System; using System.Collections.Generic; namespace Aliciza.Services.Example { public sealed class TimerService : ServiceBase, ITimerService, IServiceTickable, IServiceOrder { private readonly List _timers = new List(); private int _nextTimerId = 1; public float ElapsedTime { get; private set; } public int Order => -1000; public int Once(float delay, Action callback) { if (callback == null) { throw new ArgumentNullException(nameof(callback)); } return AddTimer(delay, 0f, 1, callback); } public int Repeat(float interval, Action callback, int repeatCount = -1, float firstDelay = -1f) { if (callback == null) { throw new ArgumentNullException(nameof(callback)); } if (interval <= 0f) { throw new ArgumentOutOfRangeException(nameof(interval), "Repeat interval must be greater than zero."); } var delay = firstDelay < 0f ? interval : firstDelay; return AddTimer(delay, interval, repeatCount, callback); } public bool Cancel(int timerId) { for (var i = 0; i < _timers.Count; i++) { if (_timers[i].Id != timerId) { continue; } _timers.RemoveAt(i); return true; } return false; } public void CancelAll() { _timers.Clear(); } public void Tick(float deltaTime) { ElapsedTime += deltaTime; for (var i = _timers.Count - 1; i >= 0; i--) { var timer = _timers[i]; timer.Remaining -= deltaTime; if (timer.Remaining > 0f) { _timers[i] = timer; continue; } timer.Callback?.Invoke(); if (timer.RepeatCount == 1) { _timers.RemoveAt(i); continue; } if (timer.RepeatCount > 1) { timer.RepeatCount--; } if (timer.Interval <= 0f) { _timers.RemoveAt(i); continue; } timer.Remaining += timer.Interval; if (timer.Remaining <= 0f) { timer.Remaining = timer.Interval; } _timers[i] = timer; } } protected override void OnInitialize() { ElapsedTime = 0f; } protected override void OnDestroyService() { CancelAll(); ElapsedTime = 0f; } private int AddTimer(float delay, float interval, int repeatCount, Action callback) { if (delay < 0f) { throw new ArgumentOutOfRangeException(nameof(delay), "Delay cannot be negative."); } if (repeatCount == 0) { throw new ArgumentOutOfRangeException(nameof(repeatCount), "Repeat count cannot be zero."); } var id = _nextTimerId++; _timers.Add(new TimerTask { Id = id, Remaining = delay, Interval = interval, RepeatCount = repeatCount, Callback = callback, }); return id; } private struct TimerTask { public int Id; public float Remaining; public float Interval; public int RepeatCount; public Action Callback; } } }