207 lines
6.5 KiB
C#
207 lines
6.5 KiB
C#
//- 跳跃
|
||
|
||
using System;
|
||
using DG.Tweening;
|
||
using UnityEngine;
|
||
using Random = UnityEngine.Random;
|
||
|
||
public enum ThrowDirection
|
||
{
|
||
TdLeft,
|
||
TdRight,
|
||
TdLeftRight,
|
||
}
|
||
|
||
public class ArcJumpBezier : MonoBehaviour
|
||
{
|
||
[Header("跳跃设置")]
|
||
|
||
public float arcHeightMin = 1f; // 弧线高度
|
||
public float arcHeightMax = 1.5f;
|
||
|
||
public float duration = 1.5f; // 跳跃时间
|
||
public Ease ease = Ease.OutQuad; // 缓动曲线
|
||
|
||
|
||
[Header("跳跃偏移")]
|
||
public float distanceMinX = 1f;
|
||
public float distanceMaxX = 2f;
|
||
public float distanceMinY = 1f;
|
||
public float distanceMaxY = 2f;
|
||
|
||
// [ContextMenu("执行弧线跳跃")]
|
||
public void PerformArcJump(Vector3 targetPosition,ThrowDirection throwDirection, Action jumpEndAction = null)
|
||
{
|
||
|
||
var worldPos = CalcTargetPosition(targetPosition, throwDirection);
|
||
|
||
Vector3 start = transform.position;
|
||
Vector3 end = worldPos;
|
||
|
||
ELog($"start: {start}=> end: {end}");
|
||
|
||
// 计算控制点(弧线顶点)
|
||
var arcHeight = Random.Range(arcHeightMin, arcHeightMax);
|
||
Vector3 control = CalculateArcControlPoint(start, end, arcHeight);
|
||
|
||
// 构建路径点
|
||
Vector3[] path = { start, control, end };
|
||
|
||
// 创建路径动画
|
||
var tween = transform.DOPath(
|
||
path: path,
|
||
duration: duration,
|
||
pathType: PathType.CatmullRom, // 平滑曲线
|
||
pathMode: PathMode.Full3D
|
||
)
|
||
// .OnUpdate(() =>
|
||
// {
|
||
// ELog($"Pos: {transform.position}, Z: {transform.position.z}");
|
||
// })
|
||
.SetEase(ease)
|
||
// .SetOptions(false, false, false); // 不闭合路径
|
||
.SetOptions(false,
|
||
lockPosition: AxisConstraint.None,
|
||
lockRotation: AxisConstraint.None
|
||
);
|
||
|
||
// // 朝向路径
|
||
// if (rotateToPath)
|
||
// {
|
||
// tween.SetLookAt(0.01f, Vector3.forward);
|
||
//
|
||
// }
|
||
|
||
|
||
tween.OnComplete(() =>
|
||
{
|
||
jumpEndAction?.Invoke();
|
||
// OnLand();
|
||
});
|
||
}
|
||
|
||
public void PerformArcJumpFailed(Vector3 targetPosition,ThrowDirection throwDirection, Action jumpEndAction = null)
|
||
{
|
||
var worldPos = CalcFailedTargetPosition(targetPosition, throwDirection);
|
||
|
||
Vector3 start = transform.position;
|
||
Vector3 end = worldPos;
|
||
|
||
// 计算控制点(弧线顶点)
|
||
// var arcHeight = Random.Range(arcHeightMin, arcHeightMax);
|
||
|
||
|
||
var arcHeight = arcHeightMax;
|
||
Vector3 control = CalculateArcControlPoint(start, end, arcHeight);
|
||
|
||
// 构建路径点
|
||
Vector3[] path = { start, control, end };
|
||
|
||
// 创建路径动画
|
||
var tween = transform.DOPath(
|
||
path: path,
|
||
duration: duration,
|
||
pathType: PathType.CatmullRom, // 平滑曲线
|
||
pathMode: PathMode.Full3D
|
||
)
|
||
// .OnUpdate(() =>
|
||
// {
|
||
// Debug.Log($"Pos: {transform.position}, Z: {transform.position.z}");
|
||
// })
|
||
.SetEase(ease)
|
||
// .SetOptions(false, false, false); // 不闭合路径
|
||
.SetOptions(false,
|
||
lockPosition: AxisConstraint.None,
|
||
lockRotation: AxisConstraint.None
|
||
);
|
||
|
||
|
||
tween.OnComplete(() =>
|
||
{
|
||
jumpEndAction?.Invoke();
|
||
});
|
||
}
|
||
private Vector3 CalcFailedTargetPosition(Vector3 targetPosition, ThrowDirection throwDirection)
|
||
{
|
||
var xDelta = Random.Range(distanceMaxX , distanceMaxX);
|
||
var yDelta = Random.Range(distanceMaxY, distanceMaxY);
|
||
// var headPos = head.transform.localPosition;
|
||
// var vector3 = new Vector3(headPos.x + xDelta, headPos.y - yDelta , headPos.z);
|
||
var headWorldPos = targetPosition;
|
||
|
||
Vector3 worldPos;
|
||
if (throwDirection == ThrowDirection.TdLeft)
|
||
{
|
||
worldPos = new Vector3(headWorldPos.x - xDelta, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
else if (throwDirection == ThrowDirection.TdRight)
|
||
{
|
||
worldPos = new Vector3(headWorldPos.x + xDelta, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
else
|
||
{
|
||
var sign = UnityEngine.Random.Range(0, 2) * 2 - 1;
|
||
worldPos = new Vector3(headWorldPos.x + xDelta * sign, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
|
||
return worldPos;
|
||
}
|
||
|
||
private Vector3 CalcTargetPosition(Vector3 targetPosition, ThrowDirection throwDirection)
|
||
{
|
||
var xDelta = Random.Range(distanceMinX, distanceMaxX);
|
||
var yDelta = Random.Range(distanceMinY, distanceMaxY);
|
||
// var headPos = head.transform.localPosition;
|
||
// var vector3 = new Vector3(headPos.x + xDelta, headPos.y - yDelta , headPos.z);
|
||
var headWorldPos = //head.transform.position;
|
||
targetPosition;
|
||
|
||
Vector3 worldPos;
|
||
if (throwDirection == ThrowDirection.TdLeft)
|
||
{
|
||
worldPos = new Vector3(headWorldPos.x - xDelta, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
else if (throwDirection == ThrowDirection.TdRight)
|
||
{
|
||
worldPos = new Vector3(headWorldPos.x + xDelta, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
else
|
||
{
|
||
var sign = Random.Range(0, 2) * 2 - 1;
|
||
worldPos = new Vector3(headWorldPos.x + xDelta * sign, headWorldPos.y - yDelta, headWorldPos.z);
|
||
}
|
||
|
||
return worldPos;
|
||
}
|
||
|
||
// 计算弧线控制点
|
||
private Vector3 CalculateArcControlPoint(Vector3 start, Vector3 end, float height)
|
||
{
|
||
// 中点 + 高度偏移
|
||
Vector3 mid = (start + end) / 2f;
|
||
|
||
// 根据高度方向自动判断(支持2D/3D)
|
||
Vector3 up = Vector3.up;
|
||
// if (Mathf.Abs(Vector3.Dot((end - start).normalized, Vector3.up)) > 0.9f)
|
||
// {
|
||
// // 如果目标在正上方,改用前方
|
||
// up = Vector3.forward;
|
||
// }
|
||
|
||
return mid + up * height;
|
||
}
|
||
|
||
private void ELog(object message)
|
||
{
|
||
#if UNITY_EDITOR
|
||
Debug.Log($"<color=orange> ArcJumpBezier {gameObject.name}=> {message} </color>");
|
||
#endif
|
||
}
|
||
|
||
// void OnLand()
|
||
// {
|
||
// Debug.Log("落地!");
|
||
// // 落地效果:震动、粒子等
|
||
// Camera.main.DOShakePosition(0.2f, 0.3f);
|
||
// }
|
||
} |