unity之贝塞尔曲线

简介

什么是贝塞尔曲线
贝塞尔曲线(Bezier curve),又称 贝兹曲线 或 贝济埃曲线 ,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,当时主要用于汽车主体设计。现主要应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,比如PhotoShop中的钢笔工具。在unity中我们一般用来生成弯路的路径点或者导弹移动轨迹等等。
什么是阶(次)
两种理解:
1、贝塞尔曲线,它的背后是一个数学函数,N阶可以理解为N次方的意思,我们也可以把三阶贝塞尔曲线叫做三次贝塞尔曲线。
2、二阶贝塞尔曲线就是在一阶贝塞尔曲线的基础上再求一次一阶贝塞尔曲线;三阶贝塞尔曲线就是在二阶贝塞尔曲线的基础上再求一次一阶贝塞尔曲线;以此类推。
简单来说就是套娃。

使用

首先要传入控制点。

    public Transform[] points;

一阶贝塞尔曲线算法:

public Vector3 lineBezier(float t)
{
    Vector3 a = points[0].position;
    Vector3 b = points[1].position;
    return a + (b - a) * t;
}

效果图
在这里插入图片描述

二阶贝塞尔曲线算法:

public Vector3 quardaticBezier(float t)
{
    Vector3 a = points[0].position;
    Vector3 b = points[1].position;
    Vector3 c = points[2].position;

    Vector3 aa = a + (b - a) * t;
    Vector3 bb = b + (c - b) * t;
    return aa + (bb - aa) * t;
}

效果图
在这里插入图片描述

三阶贝塞尔曲线算法:

public Vector3 cubicBezier(float t)
{
    Vector3 a = points[0].position;
    Vector3 b = points[1].position;
    Vector3 c = points[2].position;
    Vector3 d = points[3].position;

    Vector3 aa = a + (b - a) * t;
    Vector3 bb = b + (c - b) * t;
    Vector3 cc = c + (d - c) * t;

    Vector3 aaa = aa + (bb - aa) * t;
    Vector3 bbb = bb + (cc - bb) * t;
    return aaa + (bbb - aaa) * t;
}

效果图
在这里插入图片描述

以此类推。

扩展

贝塞尔曲线返回点的贝塞尔函数,使用线性插值的概念作为基础。下面我们使用Vector3.Lerp实现贝塞尔曲线在编辑器模式下生成路径点。
代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class CreatCurvePoints : MonoBehaviour
{
    public Transform parent;
    [SerializeField] private Transform points;                          //控制点父对象
    private List<Transform> point_tranList = new List<Transform>();     //控制点列表
    [SerializeField] private int pointCount = 100;                      //曲线点的个数
    [HideInInspector]
    public List<Vector3> line_pointList;                               //曲线点列表

    public void Init()
    {
        if (null != points && point_tranList.Count == 0)
        {
            foreach (Transform item in points)
            {
                point_tranList.Add(item);
            }
        }
        line_pointList = new List<Vector3>();
        for (int i = 0; point_tranList.Count != 0 && i < pointCount; i++)
        {
            Vector3 pos1 = Vector3.Lerp(point_tranList[0].position, point_tranList[1].position, i / (float)pointCount);
            Vector3 pos2 = Vector3.Lerp(point_tranList[1].position, point_tranList[2].position, i / (float)pointCount);
            Vector3 pos3 = Vector3.Lerp(point_tranList[2].position, point_tranList[3].position, i / (float)pointCount);
            Vector3 pos4 = Vector3.Lerp(point_tranList[3].position, point_tranList[4].position, i / (float)pointCount);
            Vector3 pos5 = Vector3.Lerp(point_tranList[4].position, point_tranList[5].position, i / (float)pointCount);

            var pos1_0 = Vector3.Lerp(pos1, pos2, i / (float)pointCount);
            var pos1_1 = Vector3.Lerp(pos2, pos3, i / (float)pointCount);
            var pos1_2 = Vector3.Lerp(pos3, pos4, i / (float)pointCount);
            var pos1_3 = Vector3.Lerp(pos4, pos5, i / (float)pointCount);
            
            var pos2_0 = Vector3.Lerp(pos1_0, pos1_1, i / (float)pointCount);
            var pos2_1 = Vector3.Lerp(pos1_1, pos1_2, i / (float)pointCount);
            var pos2_2 = Vector3.Lerp(pos1_2, pos1_3, i / (float)pointCount);
            
            var pos3_0 = Vector3.Lerp(pos2_0, pos2_1, i / (float)pointCount);
            var pos3_1 = Vector3.Lerp(pos2_1, pos2_2, i / (float)pointCount);
            
            Vector3 find = Vector3.Lerp(pos3_0, pos3_1, i / (float)pointCount);

            line_pointList.Add(find);
        }
    }

    //在scene视图显示
    void OnDrawGizmos()
    {
        Init();
        Gizmos.color = Color.yellow;
        for (int i = 0; i < line_pointList.Count - 1; i++)
        {
            Gizmos.DrawLine(line_pointList[i], line_pointList[i + 1]);
        }
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(CreatCurvePoints))]
public class CreatCurvePointsEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var ccp = target as CreatCurvePoints;
		
		//创建点
        if (GUILayout.Button("CreateCurve"))
        {
            ccp.Init();

            ccp.line_pointList.ForEach(_ =>
            {
                GameObject obj = new GameObject();
                obj.transform.SetParent(ccp.parent);
                obj.transform.position = _;
                obj.transform.rotation = Quaternion.Euler(Vector3.zero);
                obj.transform.localScale = Vector3.zero;
            });
        }

		//清除点
        if (GUILayout.Button("Clear"))
        {
            Transform parent = ccp.parent;
            for (int i = parent.childCount; i >= 1; i--)
            {
                DestroyImmediate(parent.GetChild(i - 1).gameObject, true);
            }
        }
    }
}
#endif

检视面板
在这里插入图片描述

在这里插入图片描述

效果图
在这里插入图片描述

Unity贝塞尔曲线是通过贝塞尔曲线的数学原理在Unity游戏引擎中实现的一种曲线效果。在Unity中,贝塞尔曲线可以用来创建平滑的曲线路径,并用于生成动画效果、粒子效果等。在Unity中,常用的贝塞尔曲线有一阶贝塞尔曲线、二阶贝塞尔曲线和三阶贝塞尔曲线。 一阶贝塞尔曲线是一条线性函数,通过两个控制点来定义一条直线段。二阶贝塞尔曲线是由两个一阶贝塞尔曲线的线性插值得到的,它通过三个控制点来定义一条平滑的曲线。而三阶贝塞尔曲线则是由两个二阶贝塞尔曲线的线性插值得到的,它通过四个控制点来定义一条更加复杂的曲线。 在Unity中,我们可以通过编写C#代码来实现贝塞尔曲线的计算和绘制。使用LineRenderer组件可以绘制贝塞尔曲线的路径,可以通过调整控制点的位置来改变曲线的形状。同时,我们还可以使用鼠标交互来控制曲线的控制点,实现动态的曲线效果。 总之,Unity贝塞尔曲线是一种通过数学计算和绘制技术实现的曲线效果,它可以用于游戏开发中的动画、粒子效果等场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【游戏开发进阶】玩转贝塞尔曲线,教你在Unity中画Bezier贝塞尔曲线(二阶、三阶),手把手教你推导公式](https://blog.csdn.net/linxinfa/article/details/116808549)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Unity 工具类 之 贝塞尔 Bezier 曲线](https://blog.csdn.net/u014361280/article/details/103871840)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我寄人间雪满头丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值