简单的小球沿贝塞尔曲线运动,适合场景漫游使用
贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自http://blog.csdn.net/u010019717/article/details/47684223 。仅供学习,知识分享。如有侵权,联系删除。)
贝塞尔曲线是最基本的曲线,一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的河流等。
一条贝塞尔曲线是由一组定义的控制点 P0到 Pn,在 n 调用它的顺序 (n = 1 为线性,2 为二次,等.)。第一个和最后一个控制点总是具有终结点的曲线;然而,中间两个控制点 (如果有的话) 一般不会位于曲线上 。
贝塞尔曲线包含两个控制点即 n = 2 称为线性的贝塞尔曲线
贝塞尔曲线包含三个控制点即 n = 3 称为二次贝塞尔曲线
贝塞尔曲线包含四个控制点即 n = 4,所以称为三次贝塞尔曲线。
............
以上都是复制,想看具体图解,我想有很多帖子,接下来废话不多说,直接上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BezierDrawLine : MonoBehaviour {
public List wayPoint = new List(); //路点信息(首尾表示起点和终点,中间为相对n阶偏移点)
public int pointCount = 100; //曲线上点的个数
private List linePointList;
[Range(0, 1)]
public float _time = 0.01f; //两点间的运动间隔
public Transform player; //运动物体
public Transform targetTransform; //Play目标物体
private bool isMove = false;
private float _curTimer = 0.0f; //计时
private int lineItem = 1; //目标索引
void Awake() {
//Init();
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (!isMove) return;
_curTimer += Time.deltaTime;
if (_curTimer > _time)
{
_curTimer = 0;
if (targetTransform)
player.LookAt(targetTransform);
else
player.LookAt(linePointList[lineItem]);
player.localPosition = Vector3.Lerp(linePointList[lineItem - 1], linePointList[lineItem], 1f);
lineItem++;
if (lineItem >= linePointList.Count)
lineItem = 1;
}
}
// 线性
Vector3 Bezier(Vector3 p0, Vector3 p1, float t)
{
return (1 - t) * p0 + t * p1;
}
// 二阶曲线
Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
Vector3 p0p1 = (1 - t) * p0 + t * p1;
Vector3 p1p2 = (1 - t) * p1 + t * p2;
Vector3 result = (1 - t) * p0p1 + t * p1p2;
return result;
}
// 三阶曲线
Vector3 Bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
Vector3 result;
Vector3 p0p1 = (1 - t) * p0 + t * p1;
Vector3 p1p2 = (1 - t) * p1 + t * p2;
Vector3 p2p3 = (1 - t) * p2 + t * p3;
Vector3 p0p1p2 = (1 - t) * p0p1 + t * p1p2;
Vector3 p1p2p3 = (1 - t) * p1p2 + t * p2p3;
result = (1 - t) * p0p1p2 + t * p1p2p3;
return result;
}
// n阶曲线,递归实现
public Vector3 Bezier(float t, List p)
{
if (p.Count < 2)
return p[0];
List newp = new List();
for (int i = 0; i < p.Count - 1; i++)
{
Debug.DrawLine(p[i], p[i + 1],Color.yellow);
Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];
newp.Add(p0p1);
}
return Bezier(t, newp);
}
// transform转换为vector3,在调用参数为List的Bezier函数
public Vector3 Bezier(float t, List p)
{
if (p.Count < 2)
return p[0].position;
List newp = new List();
for (int i = 0; i < p.Count; i++)
{
newp.Add(p[i].position);
}
//return Bezier(t, newp);
return MyBezier(t, newp);
}
//画出弧线
public Vector3 MyBezier(float t, List p) {
if (p.Count < 2)
return p[0];
List newp = new List();
for (int i = 0; i < p.Count - 1; i++)
{
//Debug.DrawLine(p[i], p[i + 1], Color.yellow);
Vector3 p0p1 = (1 - t) * p[i] + t * p[i + 1];
newp.Add(p0p1);
}
return MyBezier(t, newp);
}
void Init() {
linePointList = new List();
for (int i = 0; i < pointCount; i++)
{
var point = Bezier(i / (float)pointCount, wayPoint);
linePointList.Add(point);
}
if (linePointList.Count == pointCount)
isMove = true;
//Debug.LogError("isMove == " + isMove);
}
//在scene视图显示
public void OnDrawGizmos()
{
Init();
Gizmos.color = Color.yellow;
//Gizmos.DrawLine()
for (int i = 0; i < linePointList.Count - 1; i++)
{
//var point_1 = Bezier(i/(float)pointCount, wayPoint);
//var point_2 = Bezier((i+1) / (float)pointCount, wayPoint);
//两种划线方式皆可
//Gizmos.DrawLine(point_1, point_2);
Debug.DrawLine(linePointList[i], linePointList[i + 1], Color.yellow);
}
}
}
当然这几乎也是看博客来的,稍稍总结了一下:
OnDrowGizoms()这个方法是会在scene检视面板显示,划线主要是用DrawLine();
Update()中主要是小球沿曲线运动,有了路径还是很好写的
再给你们配一张参数配置:
然后.....Over,哦,欢迎吐槽!