Files
2026-06-29 21:18:33 +08:00

207 lines
6.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//- 跳跃
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);
// }
}