平时在工作中,会经常遇到一些飞行效果的调试,每次和策划调轨迹的时候都会消耗程序大量的时间,所以我就写了一个简单的工具,主要是利用DOTween做位移,贝塞尔函数算出路径点的信息,在携程里面去跑,话不多说,上代码
首先我们需要写一个N阶贝塞尔的脚本
using System.Collections.Generic;
using UnityEngine;
public class BeizerTool
{
/// <summary>
/// n次贝塞尔调用
/// </summary>
/// <param name="vertex"></param>
/// <param name="vertexCount"></param>
/// <returns></returns>
public static Vector3[] GetBeizerList_n(Vector3[] vertex, int vertexCount)
{
List<Vector3> pointList = new List<Vector3>();
pointList.Clear();
for (float ratio = 0; ratio <= 1; ratio += 1.0f / vertexCount)
{
pointList.Add(Bezier_n(vertex, ratio));
}
// pointList.Add(vertex[vertex.Length - 1]);
return pointList.ToArray();
}
private static Vector3 Bezier_n(Vector3[] vecs, float t)
{
Vector3[] temp = new Vector3[vecs.Length];
for (int i = 0; i < temp.Length; i++)
{
temp[i] = vecs[i];
}
//顶点集合有多长,曲线的每一个点就需要计算多少次。
int n = temp.Length - 1;
for (int i = 0; i < n; i++)
{
//依次计算各两个相邻的顶点的插值,并保存,每次计算都会进行降阶。剩余多少阶计算多少次。直到得到最后一条线性曲线。
for (int j = 0; j < n - i; j++)
{
temp[j] = Vector3.Lerp(temp[j], temp[j + 1], t);
}
}
//返回当前比例下曲线的点
return temp[0];
}
}
然后呢,我们需要封装一下他的调用
public void MoveToBeizer(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte,bool Isword)
{
StartCoroutine(BeizerTween(_transform, bzizerVec, time, _Compelte, Isword));
}
IEnumerator BeizerTween(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
{
Vector3[] CurrArray = BeizerTool.GetBeizerList_n(bzizerVec, (int)(time * 50));
int index = 0;
float counter = 0;
while (counter < time)
{
counter += Time.fixedDeltaTime;
if (Isword is true)
{
_transform.DOMove(CurrArray[index], 0.01f);
}
else
_transform.DOLocalMove(CurrArray[index], 0.01f);
index += 1;
if (index> CurrArray.Length-1)
{
index = CurrArray.Length - 1;
}
yield return new WaitForFixedUpdate();
}
if (_Compelte != null)
_Compelte.Invoke();
}
最后了 我们主要用unity的组件lineRender去绘制一条可见的轨迹线
using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BzLine : MonoBehaviour
{
[Header("移动的物体")]
public Transform target; // 目标物体
[Header("飞行时间控制")]
public float line_time = 5f;
[Header("重新开始按钮")]
public Button _button;
private LineRenderer lineRenderer;
[Header("起始点,n个拐点,终点")]
public List<Vector3> points = new();
private List<Vector3> points1;
[Header("是否启用世界坐标")]
public bool pos_type = true;
public Tween tween;
void Start()
{
_button.onClick.AddListener(tryAgain);
lineRenderer = gameObject.AddComponent<LineRenderer>();
points1 = new List<Vector3>();
//MoveToBeizer(target, points.ToArray(), line_time, null, true);
}
void tryAgain()
{
MoveToBeizer(target, points.ToArray(), line_time, null, pos_type);
}
public void MoveToBeizer(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
{
StartCoroutine(BeizerTween(_transform, bzizerVec, time, _Compelte, Isword));
}
IEnumerator BeizerTween(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
{
target.transform.position = points[0];
lineRenderer.positionCount = 0;
Destroy(lineRenderer);
points1.Clear();
yield return new WaitForSeconds(0.1f);
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.startWidth = 1f;
lineRenderer.endWidth = 1f;
Vector3[] CurrArray = BeizerTool.GetBeizerList_n(bzizerVec, (int)(time * 50));
int index = 0;
float counter = 0;
while (counter < time)
{
counter += Time.fixedDeltaTime;
if (Isword is true)
{
_transform.DOMove(CurrArray[index], 0.01f);
}
else
_transform.DOLocalMove(CurrArray[index], 0.01f);
index += 1;
if (index > CurrArray.Length - 1)
{
index = CurrArray.Length - 1;
}
yield return new WaitForFixedUpdate();
}
if (_Compelte != null)
_Compelte.Invoke();
//_transform.gameObject.AddComponent<CanvasGroup>().DOFade(0, 1).OnComplete(delegate() {
// Destroy(_transform.gameObject);
//});
}
void Update()
{
// 获取目标物体的位置,并添加到路径点列表
points1.Add(target.position);
// 更新LineRenderer的点
if (lineRenderer)
{
lineRenderer.positionCount = points1.Count;
lineRenderer.SetPositions(points1.ToArray());
}
}
}
这样就基本完成了一个简单的工具
下一期,我会优化这个工具,优化飞行的轨迹速度,添加动画曲线, 并且会封装一个Timer 可以控制飞行的暂停以及恢复,有时间再写吧