//- 跳跃 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($" ArcJumpBezier {gameObject.name}=> {message} "); #endif } // void OnLand() // { // Debug.Log("落地!"); // // 落地效果:震动、粒子等 // Camera.main.DOShakePosition(0.2f, 0.3f); // } }