Unity 里如何画一条曲线


在计算机图形学中,贝塞尔曲线(Bezier Curve) 是一种常见的曲线表示方法。 无论是在 2D 环境(如 HTMLCanvas)还是在 3D 游戏引擎 Unity 中,贝塞尔曲线都被广泛应用,例如路径规划、UI 动画、摄像机轨迹等。

本篇文章将带你一步步在 Unity3D 中绘制一条 三次贝塞尔曲线,并和 2D HTMLCanvas 的实现方式做一个对比。


一、什么是贝塞尔曲线?

  • 二次贝塞尔曲线:由 3 个点决定(起点 P0、控制点 P1、终点 P2)。
  • 三次贝塞尔曲线:由 4 个点决定(起点 P0、控制点 P1、控制点 P2、终点 P3)。

三次贝塞尔曲线公式为:

$$ B(t) = (1-t)^3 P0 + 3(1-t)^2 t P1 + 3(1-t) t^2 P2 + t^3 P3, \quad 0 \leq t \leq 1 $$

这条公式就是我们在 Unity 中生成曲线点的数学基础。


二、Unity3D 中绘制贝塞尔曲线的步骤

1. 创建控制点

在 Unity 场景中:

  1. 新建一个 Empty Object,命名为 BezierManager

  2. 在其下创建 4 个子物体,分别代表 P0, P1, P2, P3

    • P0 = 起点
    • P1 = 控制点 1
    • P2 = 控制点 2
    • P3 = 终点

这些点的位置可以随意调整,方便观察曲线变化。


2. 编写贝塞尔函数

新建一个 BezierCurve.cs 脚本,挂载到 BezierManager 上。

using UnityEngine;

public class BezierCurve : MonoBehaviour
{
    public Transform p0, p1, p2, p3; // 控制点
    [Range(10, 100)]
    public int segments = 50;        // 曲线分段数

    private void OnDrawGizmos()
    {
        if (p0 == null || p1 == null || p2 == null || p3 == null) return;

        Vector3 prevPoint = p0.position;
        for (int i = 1; i <= segments; i++)
        {
            float t = i / (float)segments;
            Vector3 point = CalculateCubicBezierPoint(t, p0.position, p1.position, p2.position, p3.position);
            Gizmos.color = Color.red;
            Gizmos.DrawLine(prevPoint, point);
            prevPoint = point;
        }
    }

    // 三次贝塞尔公式
    private Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {
        float u = 1 - t;
        return u * u * u * p0
             + 3 * u * u * t * p1
             + 3 * u * t * t * p2
             + t * t * t * p3;
    }
}

运行效果:在 Scene 视图中,你会看到一条由红色线段组成的平滑曲线,连接起点和终点,并受到两个控制点的影响。


3. 进一步拓展

  • 如果需要在运行时显示,可以用 LineRenderer 替代 Gizmos.DrawLine
  • 如果要在曲线上移动物体,可以在 Update() 里随时间更新参数 t 并获取曲线点坐标。

三、对比:Unity3D 与 HTMLCanvas 的异同点

相同点

  1. 数学原理相同:都依赖贝塞尔曲线公式,通过控制点插值生成曲线。
  2. 控制点数量相同:二次需要 3 个点,三次需要 4 个点。
  3. 参数 t 的使用相同:t 从 0 到 1,表示从起点到终点的插值过程。

不同点

方面HTMLCanvas (2D)Unity3D (3D)
绘制方式context.bezierCurveTo() 内置 API需手动计算点位并用线段连接
维度2D 平面 (x, y)3D 空间 (x, y, z)
坐标系左上角为 (0,0),向右下为正世界坐标系/局部坐标系,可自由旋转
用途网页绘图、图形界面路径规划、角色运动、摄像机轨迹、特效等
可视化自动绘制曲线需使用 Gizmos 或 LineRenderer

四、总结

  • HTMLCanvas 中绘制贝塞尔曲线非常方便,因为有现成 API。
  • Unity3D 中则需要自己实现公式,但好处是可以自由操作 三维空间中的曲线,并将其应用于路径规划、动画和摄像机控制等复杂场景。
  • 一旦理解了背后的数学原理,你会发现:2D 与 3D 的差异,其实就是坐标维度的不同