物体类似曲线或波浪线等效果的移动可以直接使用
/// <summary>
/// 贝塞尔曲线移动
/// </summary>
public class BezierCurveMove
{
public BezierCurveMove(Transform obj, Vector3 startPos, Vector3 endPos, float moveTime, Vector3 control1Pos)
{
_moveObject = obj;
_startPos = startPos;
_endPos = endPos;
_moveTime = moveTime;
_control1Pos = control1Pos;
_control2Pos = Vector3.zero;
}
public BezierCurveMove(Transform obj, Vector3 startPos, Vector3 endPos, float moveTime, Vector3 control1Pos, Vector3 control2Pos)
{
_moveObject = obj;
_startPos = startPos;
_endPos = endPos;
_moveTime = moveTime;
_control1Pos = control1Pos;
_control2Pos = control2Pos;
}
private Transform _moveObject;
// 物体移动的时间
private float _moveTime = 1f;
// 控制位置1
private Vector3 _control1Pos;
// 控制位置2
private Vector3 _control2Pos;
// 起始位置
private Vector3 _startPos;
// 结束位置
private Vector3 _endPos;
// 记录物体开始移动的时间
private float _startTime;
// 当前状态
private bool _isMove;
public bool IsMove()
{
return _isMove;
}
// 回调(用于移动结束后执行)
Action _callBack = null;
public void Start(Action callBack = null)
{
// 记录回调
_callBack = callBack;
// 将状态改为开始移动
_isMove = true;
// 记录物体开始移动的时间
_startTime = Time.time;
// 启动协程,移动物体
BezierCurveMoveHelper.Instance.StartCoroutine(Move());
}
private IEnumerator Move()
{
// 规定时间内可移动
while (Time.time <= _startTime + _moveTime)
{
// 计算当前时间点在曲线上的位置
float t = (Time.time - _startTime) / _moveTime;
// 使用贝塞尔曲线计算物体的位置
Vector3 newPos = Vector3.zero;
if (_control2Pos == Vector3.zero)
{
newPos = CalculateBezierPoint(t, _startPos, _control1Pos, _endPos);
}
else
{
newPos = CalculateBezierPoint(t, _startPos, _control1Pos, _control2Pos, _endPos);
}
// 更新物体的位置
_moveObject.position = newPos;
// 暂停一帧,继续执行下一帧
yield return new WaitForEndOfFrame();
}
// 移动结束后,将物体移动到目标位置
_moveObject.position = _endPos;
// 将状态改为结束移动
_isMove = false;
// 判断回调不为空执行回调
if (_callBack != null)
{
_callBack();
_callBack = null;
}
}
// 根据贝塞尔曲线公式计算曲线上的点
private Vector3 CalculateBezierPoint(float t, Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint)
{
//二阶公式:1-t^2 * P0 +
//2t * 1-t * P1 +
//t^2 * P2
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 point =
uu * startPoint +
2 * u * t * controlPoint +
tt * endPoint;
return point;
}
private Vector3 CalculateBezierPoint(float t, Vector3 startPoint, Vector3 control1Point, Vector3 control2Point, Vector3 endPoint)
{
//三阶公式:(1-t)^3 * P0 +
//3t * (1-t)^2 * P1 +
//3 * 1-t * t^2 * P2 +
//t^3 * P3
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 point =
uuu * startPoint +
3 * uu * t * control1Point +
3 * u * tt * control2Point +
ttt * endPoint;
return point;
}
}
public class BezierCurveMoveHelper : MonoBehaviour
{
private static BezierCurveMoveHelper _instance = null;
private static readonly object locker = new object();
public static BezierCurveMoveHelper Instance
{
get
{
if (_instance == null)
{
lock (locker)
{
if (_instance == null)
{
_instance = new BezierCurveMoveHelper();
}
}
}
return _instance;
}
}
}
使用方法: