Unity之Dotween实现多个物体从开始位置按照弧形轨迹移动
using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI_ZhuZhan_Effect : MonoBehaviour {
public GameObject[] m_EffectList;
[Header("贝塞尔曲线点的数量")]
public int m_VecPointNum = 3;
[Header("贝塞尔曲线坡峰")]
public int m_SlopePeak = 50;
//[Header("到终点的偏移距离,与斜率相乘得到最终位置点")]
//public float m_OffectValue = 130;
//[Header("正弦函数坡长")]
//public float m_SlopeLength = 3;
//[Header("正弦函数坡峰数组")]
//public float[] m_SlopePeak;
public void Init(Vector3 startPoint, Vector3 endPoint, Action action)
{
float distance = Vector3.Distance(startPoint, endPoint) / 180;
//m_SlopeLength = 50;
//float SlopeValue = Mathf.Atan2((endPoint.x - startPoint.x), (endPoint.z - startPoint.z));
//float angle = SlopeValue * (180 / Mathf.PI);
//angle = 1 - Mathf.Abs(angle) / 180;
//m_OffectValue = angle * 200;
//Debug.Log("斜率:" + angle);
Vector3 centerPos = new Vector3((startPoint.x + endPoint.x) / 2, endPoint.y, (startPoint.z + endPoint.z) / 2);
float SlopeValue1 = (endPoint.x - startPoint.x) / (endPoint.z - startPoint.z);
float SlopeValue2 = (-1)/SlopeValue1;
float b = centerPos.x - centerPos.z * SlopeValue2;
Sequence sequence = DOTween.Sequence();
int index = 0;
for (int i = 0; i < m_EffectList.Length; i++)
{
m_EffectList[i].transform.position = startPoint;
if (index == 0)
{
centerPos = new Vector3(SlopeValue2*((startPoint.z + endPoint.z) / 2 + (m_SlopePeak + distance) / SlopeValue2) + b, endPoint.y, (startPoint.z + endPoint.z) / 2 + (m_SlopePeak + distance) / SlopeValue2);
}
else if(index == 1)
{
centerPos = new Vector3(SlopeValue2 * ((startPoint.z + endPoint.z) / 2 - (m_SlopePeak + distance) / SlopeValue2) + b, endPoint.y, (startPoint.z + endPoint.z) / 2 - (m_SlopePeak + distance) / SlopeValue2);
}
else
{
centerPos = new Vector3((startPoint.x + endPoint.x) / 2, endPoint.y, (startPoint.z + endPoint.z) / 2);
index = 0;
}
index++;
Vector3[] path = GetBeizerList(startPoint, centerPos, endPoint, m_VecPointNum);//m_SlopePeak[i], 0, m_OffectValue * (SlopeValue <= 0 ? 1 : -1)
if (i==0)
{
sequence.Append(m_EffectList[i].transform.DOLocalPath(path, 1.5f, PathType.CatmullRom));
}
else
{
sequence.Insert(0,m_EffectList[i].transform.DOLocalPath(path, 1.5f, PathType.CatmullRom));
}
}
sequence.AppendCallback(delegate ()
{
action.InvokeIfNotNull();
});
}
/// <summary>
/// 获取存储贝塞尔曲线点的数组
/// </summary>
/// <param name="startPoint"></param>起始点
/// <param name="controlPoint"></param>控制点
/// <param name="endPoint"></param>目标点
/// <param name="segmentNum"></param>采样点的数量
/// <returns></returns>存储贝塞尔曲线点的数组
public Vector3[] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int segmentNum)//, float slopePeak, float offectValue
{
Vector3[] path = new Vector3[segmentNum+1];
path[0] = startPoint;
for (int i = 1; i <= segmentNum; i++)
{
float t = i / (float)segmentNum;
Vector3 pixel = CalculateCubicBezierPoint(t, startPoint,
controlPoint, endPoint);
//if (slopePeak!=0)
//{
// float innner = (2 * (float)Mathf.PI) / m_SlopeLength;
// pixel.x = (float)Mathf.Sin(innner * pixel.z) * slopePeak - offectValue;
//}
path[i] = pixel;
}
path[segmentNum] = endPoint;
return path;
}
/// <summary>
/// 根据T值,计算贝塞尔曲线上面相对应的点
/// </summary>
/// <param name="t"></param>T值
/// <param name="p0"></param>起始点
/// <param name="p1"></param>控制点
/// <param name="p2"></param>目标点
/// <returns></returns>根据T值计算出来的贝赛尔曲线点
private Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
}