提交修改
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user