105 lines
3.4 KiB
C#
105 lines
3.4 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 static readonly int VelocityForward = Animator.StringToHash("VelocityForward");
|
|
|
|
private Func<HoloCop, float, bool> _action;
|
|
|
|
[SerializeField] private MovementController movementController;
|
|
[SerializeField] private KinematicCharacterMotor motor;
|
|
[SerializeField] private KinematicCharacterMotor originMotor;
|
|
[SerializeField] private Animator animator;
|
|
[SerializeField] private Animator originAnimator;
|
|
|
|
public MovementController Controller => movementController;
|
|
public Animator Animator => animator;
|
|
|
|
private Vector3 _initialMotorPosition;
|
|
private Quaternion _initialMotorRotation;
|
|
|
|
private int _initialAnimationState;
|
|
private float _initialNormalizedTime;
|
|
|
|
private void Snapshot()
|
|
{
|
|
_initialMotorPosition = originMotor.TransientPosition;
|
|
_initialMotorRotation = originMotor.TransientRotation;
|
|
|
|
AnimatorStateInfo stateInfo = originAnimator.GetCurrentAnimatorStateInfo(0);
|
|
_initialAnimationState = stateInfo.shortNameHash;
|
|
_initialNormalizedTime = stateInfo.normalizedTime;
|
|
|
|
animator.SetFloat(VelocityForward, originAnimator.GetFloat(VelocityForward));
|
|
|
|
animator.Play(_initialAnimationState, 0, _initialNormalizedTime);
|
|
animator.Update(0f);
|
|
}
|
|
|
|
private void ReturnToSnapshot()
|
|
{
|
|
bool prevRootMotion = animator.applyRootMotion;
|
|
|
|
animator.Play(_initialAnimationState, 0, _initialNormalizedTime);
|
|
animator.Update(0f);
|
|
|
|
animator.transform.localPosition = Vector3.zero;
|
|
animator.transform.localRotation = Quaternion.identity;
|
|
|
|
originMotor.SetPositionAndRotation(_initialMotorPosition, _initialMotorRotation);
|
|
|
|
Physics.SyncTransforms();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
} |