Unity中我们常见一些有弧度的曲线 足球射门之类的我们可以用到贝塞尔曲线
数学原理
线性贝塞尔曲线
线性贝塞尔曲线
看起来类似unity自带的Lerp一样
二次贝塞尔曲线
二次贝塞尔曲线
从绿色线的头部到尾部 同时绿色线的头从P0→P1
绿色线的尾从P1-P2
三次贝塞尔曲线和N次
三次贝塞尔曲线
然后我们发现三次两个绿线又出来个蓝线 根据蓝线移动
N次的图就没找到 反正就是在一堆点之内控制移动 N次依此类推
Unity应用
直接整一个工具类使用 这是常用的2次贝赛尔曲线
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 二次贝塞尔函数工具类
/// </summary>
public class BezierUtils : MonoBehaviour
{
/// <summary>
/// 根据T值,计算贝赛尔曲线上面对应的点
/// </summary>
/// <param name="t"></param>T值
/// <param name="p0"></param>起始点
/// <param name="p1"></param>控制点
/// <param name="p2"></param>目标点
/// <returns></returns>根据T值计算出来的贝赛尔曲线
/// (1-t)2P0+2(1-t)tP1+t2P2
static 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;//(1-t)2P0
p += 2 * u * t * p1;//2(1-t)tP1
p += tt * p2;//t2P2
return p;
}
/// <summary>
/// 获取一个贝赛尔曲线点的数组
/// </summary>
/// <param name="startPoint"></param>起始点
/// <param name="contiolPoint"></param>控制点
/// <param name="endPoint"></param>目标点
/// <param name="segmentNum"></param>采样点的数量 精度
/// <returns></returns>一个贝赛尔曲线的数组
public static List<Vector3> GetBeizerList(Vector3 startPoint, Vector3 contiolPoint, Vector3 endPoint, int segmentNum)
{
List<Vector3> path = new List<Vector3>();
// Vector3[] path = new Vector3[segmentNum];
//若长度为5 采样点为 1/5 2/5 3/5 4/5 5/5k
for (int i = 1; i <= segmentNum; i++)
{
float t = i / (float)segmentNum;
Vector3 pixel = CalculateCubicBezierPoint(t, startPoint, contiolPoint, endPoint);
path.Add(pixel);
Debug.Log(path[i - 1]);
}
return path;
}
}
然后是测试类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestBezier : MonoBehaviour
{
[Header("开始目标")]
public Transform targe1;
[Header("控制点")]
public Transform controlPoint;
[Header("终点目标")]
public Transform targe2;
[Header("精确度")]
public int accuracy = 5;
[Header("速度")]
public float speed = 1;
float t;
[Header("是否开始移动")]
public bool isMove = false;//手动控制
List<Vector3> path;
void Awake()
{
path = BezierUtils.GetBeizerList(targe1.position, controlPoint.position, targe2.position, accuracy);
}
/// <summary>
/// 寻路模拟
/// </summary>
/// <param name="path"></param>
public void FindPath(List<Vector3> path)
{
t += Time.deltaTime;
if (t >= speed)
{
t = 0;
if (path != null && path.Count > 0)
{
var startPos = path[0];
targe1.transform.position = startPos;
path.Remove(startPos);
}
}
}
// Update is called once per frame
void Update()
{
if (isMove == true)
{
FindPath(path);
}
}
}
更多unity2018的功能介绍请到paws3d爪爪学院查找。链接https://www.paws3d.com/learn/,也可以加入unity学习讨论群935714213
近期更有资深开发人士直播分享unity开发经验,详情请进入官网或加入QQ群了解