Unity 必学的小知识

前言

在unity中我们经常会用到一些曲线在解决自己的需求,比如说高空抛物显示物体运动轨迹,编辑运动轨迹,导弹发射路径等等。本小白作为unity初学者,接下来与大家一起分享下贝塞尔曲线的知识


一、贝塞尔曲线是什么?

Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。
转自:http://blog.csdn.net/tianhai110/article/details/2203572

二、推导过程

1.一阶曲线

演示图:
在这里插入图片描述

公式如下:

B(t) = P0 + (P1-P0)t 整理如下:

Alt
解释如下:
如图,图中运动的黑点点就是我们要求的点,这个点一定是在曲线上(因为两个点只能形成一条直线,我们在这暂且把这条直线认为是一条特殊的“曲线”)的。公式中B(t)即为黑点的坐标,为了方便起见就叫QP0为起点,P1为终点,t为向量P0Q在向量P0P1中所占的比例,t∈[0,1],当t=1时,P0Q = P0P1。

2. 二阶曲线

有了一阶曲线的基础,二阶曲线就容易多了。
演示图:
在这里插入图片描述

公式如下:
如图所示,我们所求的黑点Q并不在两条向量上,而在这条绿色向量Q1Q2上,Q1为P0P1上的点,Q2为P1P2上的点,如何如何求点Q1和Q2呢?这就用到上面的公式了:

Q1 = (1-t)P0 + t(P1)
Q2 = (1-t)P1 + t(P2)
Q = (1-t)Q1 + tQ2
t∈[0,1]

最终整合公式,并将Q用B(t)代替,得到下面公式:
在这里插入图片描述

tips:
细心的老爷们发现没有,P0P1为曲线在P0处的切线,P1P2P为曲线在P2处的切线,绿色线段为曲线在Q点的切线。

3.三阶曲线

三阶曲线和二阶曲线有异曲同工之处
演示图:
在这里插入图片描述
公式:
用计算二阶的方法得出下面公式

在这里插入图片描述

4.多阶曲线

四阶演示图:
在这里插入图片描述

五阶演示图:
在这里插入图片描述
通用公式:
在这里插入图片描述
用二项式表达为
在这里插入图片描述

三、案例展示(三阶曲线)

代码:

using System.Collections.Generic;
using UnityEngine;

public class DrawBezierLine : MonoBehaviour
{
    public Transform[] fourPoints = new Transform[4];//四个拖拽点的物体transform

    int bezierPointCounts = 10;//两个拖拽点之间贝塞尔点的个数

    //计算并获得贝塞尔点的集合
    List<Vector3> GetBezierPoints()
    {
        List<Vector3> pointList = new List<Vector3>();
        for (int i = 0; i <= bezierPointCounts; i++)
        {
            if (fourPoints.Length >= 4)
            {
                Vector3 p0 = fourPoints[0].position;//第一个点
                Vector3 p1 = fourPoints[1].position;//第二个点
                Vector3 p2 = fourPoints[2].position;//第三个点
                Vector3 p3 = fourPoints[3].position;//第四个点

                float t = i / (bezierPointCounts * 1.0f);//所占比例


                //1.利用一阶公式递推
                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;
                Vector3 bezierPoint = (1 - t) * p0p1p2 + t * p1p2p3;


                2.利用通用公式二次项展开
                //Vector3 bezierPoint = p0 * Mathf.Pow((1 - t), 3) + 3 * p1 * t * Mathf.Pow((1 - t), 2) + 3 * p2 * Mathf.Pow(t, 2) * (1 - t) + p3 * Mathf.Pow(t, 3);
                pointList.Add(bezierPoint);
            }
        }
        return pointList;
    }
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        //将四个拖拽点用蓝色绘制
        if (fourPoints.Length >= 4) 
        {
            for (int i = 0; i < fourPoints.Length - 1; i++)
            {
                Gizmos.DrawLine(fourPoints[i].position, fourPoints[i + 1].position);
            }
        }
        //计算得到曲线上点的集合
        List<Vector3> bezierPoints = GetBezierPoints();

        //将计算出来的贝塞尔曲线上的点用红色绘制出来
        Gizmos.color = Color.red;
        for (int j = 0; j < bezierPoints.Count - 1; j++)
        {
            Gizmos.DrawLine(bezierPoints[j], bezierPoints[j + 1]);
        }
    }

}

附上成果:
在这里插入图片描述


总结

本小白刚接触unity不久,今后会记录并分享一些有用的知识点,可能有些地方写的不太好,希望有人斧正!

资料参考: https://www.jianshu.com/p/8f82db9556d2.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值