Unity中利用贝塞尔曲线插值美化连线

文章发布时间:

最后更新时间:

页面浏览: 加载中...

贝塞尔曲线

贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等。在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具。

学习视频

生成曲线的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 计算中间控制点
Vector3 startPos = mapLayout.linePositionList[i].startPos.ToVector3(); //起始点
Vector3 endPos = mapLayout.linePositionList[i].endPos.ToVector3(); //结束点

// 沿X轴延伸的中间点(总长度的1/2处)
float xSegmentLength = (endPos.x - startPos.x) / 2;
Vector3 midPoint1 = startPos + new Vector3(xSegmentLength, 0, 0);
Vector3 midPoint2 = endPos - new Vector3(xSegmentLength, 0, 0);
//这里是我根据我的需求是做出像明日方舟肉鸽中关卡的连线
//所以计算出两个点的位置作为插值
//我的四个点是如下
// ·------------·
// |
// ·-----------·

// 创建包含曲线路径的四个关键点
Vector3[] path = new Vector3[] {
startPos, // 起点
midPoint1, // 第一段X轴终点
midPoint2, // 曲线过渡起点
endPos // 终点
};
// 用LineRenderer绘制平滑曲线
var line = Instantiate(linePrefab, transform);
line.positionCount = path.Length;
line.SetPositions(path);
// 添加曲线平滑处理(需要添加Line脚本的修改)
line.gameObject.GetComponent<LineCurveController>().SmoothCurve();

lines.Add(line);

挂载在line上的脚本LineCurveController代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using UnityEngine;

[RequireComponent(typeof(LineRenderer))]
public class LineCurveController : MonoBehaviour
{
public static int curveResolution = 20; // 曲线细分精度

public void SmoothCurve()
{
LineRenderer lr = GetComponent<LineRenderer>();
if (lr.positionCount < 4) return;

Vector3[] originalPoints = new Vector3[4];
lr.GetPositions(originalPoints);

// 生成贝塞尔曲线点
Vector3[] curvePoints = new Vector3[curveResolution];
for (int i = 0; i < curveResolution; i++)
{
float t = i / (float)(curveResolution - 1);
curvePoints[i] = CalculateBezierPoint(t,
originalPoints[0],
originalPoints[1],
originalPoints[2],
originalPoints[3]);
}

lr.positionCount = curveResolution;
lr.SetPositions(curvePoints);
}

// 三次贝塞尔曲线计算公式
private Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;

Vector3 p = uuu * p0;
p += 3 * uu * t * p1;
p += 3 * u * tt * p2;
p += ttt * p3;

return p;
}
}