Files
Hasebe/Assets/Code/OfficeGame/BattleMode/Actions/HoloCopy/HoloCop.cs
T
2026-10-28 14:02:58 +03:00

91 lines
2.7 KiB
C#

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<HoloCop, float, bool> _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<Animator>();
movementController = GetComponent<MovementController>();
motor = GetComponent<KinematicCharacterMotor>();
}
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<HoloCop, float, bool> 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);
}
}
}
}