159 lines
5.0 KiB
C#
159 lines
5.0 KiB
C#
using UnityEngine;
|
|
|
|
namespace NBF
|
|
{
|
|
public class ParabolaPlayerThrowAnimation : IPlayerThrowAnimation
|
|
{
|
|
private const int TrajectorySampleCount = 24;
|
|
|
|
private readonly float _minThrowDistance;
|
|
private readonly float _maxThrowDistance;
|
|
private readonly float _throwDuration;
|
|
private readonly float _throwArcHeight;
|
|
private readonly float _targetHeightOffset;
|
|
private readonly AnimationCurve _throwHeightCurve;
|
|
private readonly Vector3[] _lastTrajectoryPoints = new Vector3[TrajectorySampleCount + 1];
|
|
|
|
private bool _hasLastTrajectory;
|
|
private float _chargedProgress;
|
|
private float _castElapsedTime;
|
|
private Vector3 _castStartPos;
|
|
private Vector3 _castTargetPos;
|
|
private LureController _castingLure;
|
|
|
|
public bool IsPlaying => _castingLure != null;
|
|
|
|
public ParabolaPlayerThrowAnimation(
|
|
float minThrowDistance = 6f,
|
|
float maxThrowDistance = 25f,
|
|
float throwDuration = 0.65f,
|
|
float throwArcHeight = 4f,
|
|
float targetHeightOffset = 0f,
|
|
AnimationCurve throwHeightCurve = null)
|
|
{
|
|
_minThrowDistance = minThrowDistance;
|
|
_maxThrowDistance = maxThrowDistance;
|
|
_throwDuration = throwDuration;
|
|
_throwArcHeight = throwArcHeight;
|
|
_targetHeightOffset = targetHeightOffset;
|
|
_throwHeightCurve = throwHeightCurve ?? AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
|
|
}
|
|
|
|
public void Play(ThrowAnimationRequest request)
|
|
{
|
|
if (request.Lure == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Stop(snapToTarget: false);
|
|
|
|
_castingLure = request.Lure;
|
|
_chargedProgress = Mathf.Clamp01(request.ChargedProgress);
|
|
_castElapsedTime = 0f;
|
|
|
|
var lureBody = request.Lure.RBody;
|
|
_castStartPos = request.StartPosition;
|
|
|
|
Vector3 forward = request.Forward;
|
|
forward.y = 0f;
|
|
if (forward.sqrMagnitude < 0.001f)
|
|
{
|
|
forward = Vector3.forward;
|
|
}
|
|
|
|
float distance = Mathf.Lerp(_minThrowDistance, _maxThrowDistance, _chargedProgress);
|
|
_castTargetPos = _castStartPos + forward.normalized * distance;
|
|
_castTargetPos.y = _castStartPos.y + _targetHeightOffset;
|
|
|
|
CacheTrajectoryPoints();
|
|
|
|
lureBody.isKinematic = true;
|
|
lureBody.useGravity = false;
|
|
lureBody.linearVelocity = Vector3.zero;
|
|
lureBody.angularVelocity = Vector3.zero;
|
|
lureBody.position = _castStartPos;
|
|
}
|
|
|
|
public void Tick(float deltaTime)
|
|
{
|
|
DrawLastTrajectory();
|
|
UpdateCastAnimation(deltaTime);
|
|
}
|
|
|
|
public void Stop(bool snapToTarget)
|
|
{
|
|
if (_castingLure == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var lureBody = _castingLure.RBody;
|
|
if (snapToTarget)
|
|
{
|
|
_castingLure.transform.position = _castTargetPos;
|
|
lureBody.position = _castTargetPos;
|
|
}
|
|
|
|
lureBody.linearVelocity = Vector3.zero;
|
|
lureBody.angularVelocity = Vector3.zero;
|
|
lureBody.useGravity = true;
|
|
lureBody.isKinematic = false;
|
|
|
|
_castingLure = null;
|
|
}
|
|
|
|
private void UpdateCastAnimation(float deltaTime)
|
|
{
|
|
if (_castingLure == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float duration = Mathf.Max(_throwDuration, 0.01f);
|
|
_castElapsedTime += deltaTime;
|
|
float progress = Mathf.Clamp01(_castElapsedTime / duration);
|
|
|
|
_castingLure.transform.position = EvaluateTrajectoryPosition(progress);
|
|
|
|
if (progress >= 1f)
|
|
{
|
|
Stop(snapToTarget: true);
|
|
}
|
|
}
|
|
|
|
private void CacheTrajectoryPoints()
|
|
{
|
|
for (int i = 0; i <= TrajectorySampleCount; i++)
|
|
{
|
|
float progress = i / (float)TrajectorySampleCount;
|
|
_lastTrajectoryPoints[i] = EvaluateTrajectoryPosition(progress);
|
|
}
|
|
|
|
_hasLastTrajectory = true;
|
|
}
|
|
|
|
private Vector3 EvaluateTrajectoryPosition(float progress)
|
|
{
|
|
Vector3 position = Vector3.Lerp(_castStartPos, _castTargetPos, progress);
|
|
float arc = _throwHeightCurve.Evaluate(progress) * _throwArcHeight * _chargedProgress;
|
|
position.y += arc;
|
|
return position;
|
|
}
|
|
|
|
private void DrawLastTrajectory()
|
|
{
|
|
if (!_hasLastTrajectory)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 1; i <= TrajectorySampleCount; i++)
|
|
{
|
|
Debug.DrawLine(_lastTrajectoryPoints[i - 1], _lastTrajectoryPoints[i], Color.yellow);
|
|
}
|
|
|
|
Debug.DrawRay(_lastTrajectoryPoints[TrajectorySampleCount], Vector3.up * 0.3f, Color.cyan);
|
|
}
|
|
}
|
|
} |