using System; using System.Threading; using Code.Game.Gameplay.Player; using Code.OfficeGame.BattleMode.Timeline; using Cysharp.Threading.Tasks; using KinematicCharacterController; using UnityEngine; using UnityEngine.Serialization; namespace Code.OfficeGame.BattleMode.Actions.HoloCopy { public class HoloCop : MonoBehaviour { private Func _action; [SerializeField] private MovementController movementController; [SerializeField] private KinematicCharacterMotor motor; [SerializeField] private Animator animator; public MovementController Controller => movementController; public Animator Animator => animator; private Vector3 _initialPosition; private Quaternion _initialRotation; private int _initialAnimationState; private void Awake() { animator = GetComponentInChildren(); movementController = GetComponent(); motor = GetComponent(); } private void Snapshot() { _initialPosition = motor.transform.position; _initialRotation = motor.transform.rotation; _initialAnimationState = animator.GetCurrentAnimatorStateInfo(0).shortNameHash; } private void ReturnToSnapshot() { motor.SetPositionAndRotation(_initialPosition, _initialRotation); animator.Play(_initialAnimationState, 0); } public async UniTask Simulate(Func action, CancellationToken ctx) { _action = action; float accumulator = 0f; Snapshot(); try { gameObject.SetActive(true); while (!ctx.IsCancellationRequested) { await UniTask.Yield(PlayerLoopTiming.Update, ctx); accumulator += Time.unscaledDeltaTime; while (accumulator >= BattleTimeline.TickDelta) { accumulator -= BattleTimeline.TickDelta; if (_action == null) return; bool result = _action(this, BattleTimeline.TickDelta); animator.Update(BattleTimeline.TickDelta); Physics.Simulate(BattleTimeline.TickDelta); Physics.SyncTransforms(); if (result) ReturnToSnapshot(); } } } finally { ReturnToSnapshot(); gameObject.SetActive(false); } } } }