using System.Collections.Generic; using System.Threading; using Code.OfficeGame.BattleMode.Actions; using Cysharp.Threading.Tasks; using UnityEngine; namespace Code.OfficeGame.BattleMode.Timeline { public class BattleTimeline { public const int TicksPerSecond = 60; public const float TickDelta = 1f / TicksPerSecond; public int CurrentBattleFrame { get; private set; } private List _entities; public async UniTask RunBattleLoopAsync(List entities, CancellationToken ct) { _entities = entities; CurrentBattleFrame = 0; await DecideActions(_entities, ct); while (!IsBattleOver() && !ct.IsCancellationRequested) { List entitiesNeedOrders = await PlayTimelineUntilPause(ct); await DecideActions(entitiesNeedOrders, ct); } } private async UniTask DecideActions(List entityActionMakers, CancellationToken ct) { foreach (var entity in entityActionMakers) { Debug.Log($"Deciding action for {entity.name}"); await entity.DecideAction(ct); } } private async UniTask> PlayTimelineUntilPause(CancellationToken ct) { float accumulator = 0f; var readyEntities = new List(); while (readyEntities.Count == 0 && !ct.IsCancellationRequested) { await UniTask.Yield(PlayerLoopTiming.Update, ct); accumulator += Time.unscaledDeltaTime; while (accumulator >= TickDelta) { accumulator -= TickDelta; SimulateSingleFrame(readyEntities); if (readyEntities.Count > 0) return readyEntities; } } return readyEntities; } private void SimulateSingleFrame(List outReadyEntities) { CurrentBattleFrame++; foreach (var entity in _entities) { entity.CurrentAction.Tick(TickDelta); } foreach (var entity in _entities) { entity.animator.Update(TickDelta); } Physics.Simulate(TickDelta); Physics.SyncTransforms(); foreach (var entity in _entities) { if (entity.Finished) { outReadyEntities.Add(entity); } } } private bool IsBattleOver() => false; } }