Unity游戏中使用贝塞尔曲线_u010019717的博客-程序员宝宝_贝塞尔曲线游戏app

技术标签: unity  ui  unity3d Editor私人定制  unity3d  camera  

孙广东   2015.8.15

比如在3D rpg游戏中,我们想设置弹道,不同的轨迹类型!


目的:这篇文章的主要目的是要给你关于在游戏如何使用贝塞尔曲线的基本想法。

         贝塞尔曲线是最基本的曲线,一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的河流等。

        一条贝塞尔曲线是由一组定义的控制点 P0到 Pn,在 n 调用它的顺序 (n = 1 为线性,2 为二次,等.)。第一个和最后一个控制点总是具有终结点的曲线;然而,中间两个控制点 (如果有的话) 一般不会位于曲线上 。

贝塞尔曲线包含两个控制点即 n = 2 称为线性的贝塞尔曲线

贝塞尔曲线包含三个控制点即 n = 3 称为二次贝塞尔曲线

贝塞尔曲线包含四个控制点即 n = 4,所以称为三次贝塞尔曲线。


贝塞尔曲线返回点的贝塞尔函数,使用线性插值的概念作为基础。所以,让我们了解什么首先是线性插值。

两个点之间的线性插值的点获取那两个点之间,0 <= t <= 1,像 Mathf.Lerp 。

插值点,与 P 公式P0和 P1可以写成,

P = P0+ t (P1 - P0),0 <= t <= 1

在这里,为得到插值的点我们添加 tth指向 P 的分数与这两个之间的距离0.所以,

For T = 0,P = P0.

For T = 1,P = P1.

For T = 0.5,P =  P0和 P1间的点.


线性的贝塞尔曲线:

线性的贝塞尔曲线有两个控制点。为给出了两个点 P0和 P1一个线性的贝塞尔曲线是只是这两个点之间的直线。曲线是相当于线性插值给出,

B(t) = P0+ t (P1 -  P0) = (1-t) P0 + tP1    ,0 <= t <= 1

        线性贝塞尔曲线如何计算出来的是如下所示:




二次贝塞尔曲线:

        二次贝塞尔曲线具有三个控制点。二次贝塞尔曲线是点对点的两个线性贝塞尔曲线的线性插值。为给出了三个点 P0、P1和 P2一条二次贝塞尔曲线,其实是两条线性的贝塞尔曲线,线性贝塞尔曲线的 P0和 P1和   线性贝塞尔曲线P1和 P2.     所以,给出二次贝塞尔曲线 :

B(t) = (1-t) BP0P1(t) + t BP1P2(t),0 <= t <= 1

B(t) = (1-t) [(1-t) P0 + tP1] + t [(1-t) P1+ tP2],0 <= t <= 1


通过重新排列上述方程,

B(t) = (1-t)2P0+ 2 (1-t) tP1 + t2P2,   0 <= t <= 1

二次贝塞尔曲线动画计算如下所示:



三次贝塞尔曲线:

三次方贝塞尔曲线具有四个控制点。二次贝塞尔曲线是  点对点的两条二次贝塞尔曲线的线性插值。对于给出的四个点 P0、P1、P2和 P3三次方贝塞尔曲线,是二次贝塞尔曲线P0、P1和 P2和   二次贝塞尔曲线P1、P2和 P3 得到的 线性插值  .所以,给出三次方贝塞尔曲线

B(t) = (1-t) BP0,P1,P2(t) + t BP1,P2,P3(t),0 <= t <= 1

B(t) = (1-t) [(1-t)2P0+ 2 (1-t) tP1 + t2P2] + t [(1-t)2P1+ 2 (1-t) tP2 + t2P3],0 <= t <= 1


通过重新排列上述方程中,

B(t) = (1-t)3P0 + 3(1-t)2tP1+ 3 (1-t) t2P2 + t3P3           0 <= t <= 1

三次贝塞尔曲线计算如下所示:


所以,一般可以作为点对点的线性插值获得从两个相应的贝赛尔曲线的程度 n-1 的两个点定义程度 n 的贝塞尔曲线(就是高级的是两个低一级的线性插值)。

           在大多数应用程序使用两种二次或三次方贝塞尔函数。然而,你总可以使用更高程度贝塞尔函数绘制更复杂的曲线,但较高程度贝塞尔函数的计算是比较复杂和增加处理开销。所以,而不是使用更高的学位贝塞尔函数绘制更复杂的曲线,你可以多次使用两种二次或三次方贝塞尔函数。在这里,我创建了一个演示和绘制的∞形曲线,使用三次方贝塞尔函数中循环,如下所示。


若要创建一条曲线,如上所示,请创建场景,如下所示:



现在,将Bezier.cs脚本附加到  Bezier Manager

Bezier.cs:


using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(LineRenderer))]
public class Bezier : MonoBehaviour
{
    public Transform[] controlPoints;
    public LineRenderer lineRenderer;
    
    private int curveCount = 0;    
    private int layerOrder = 0;
    private int SEGMENT_COUNT = 50;
    
        
    void Start()
    {
        if (!lineRenderer)
        {
            lineRenderer = GetComponent<LineRenderer>();
        }
        lineRenderer.sortingLayerID = layerOrder;
        curveCount = (int)controlPoints.Length / 3;
    }

    void Update()
    {
       
        DrawCurve();

    }
    
    void DrawCurve()
    {
        for (int j = 0; j <curveCount; j++)
        {
            for (int i = 1; i <= SEGMENT_COUNT; i++)
            {
                float t = i / (float)SEGMENT_COUNT;
                int nodeIndex = j * 3;
                Vector3 pixel = CalculateCubicBezierPoint(t, controlPoints [nodeIndex].position, controlPoints [nodeIndex + 1].position, controlPoints [nodeIndex + 2].position, controlPoints [nodeIndex + 3].position);
                lineRenderer.SetVertexCount(((j * SEGMENT_COUNT) + i));
                lineRenderer.SetPosition((j * SEGMENT_COUNT) + (i - 1), pixel);
            }
            
        }
    }
        
    Vector3 CalculateCubicBezierPoint(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;
    }
}

在这里,CalculateCubicBezierPoint 函数是 Cubiz 贝塞尔函数,我已解释了上面执行。DrawCurve 函数绘制两条 三次方贝塞尔曲线。


Between P0, P0- control Point1, P1- control Point1 and P1.

Between P1, P1- control Point1, P0- control Point2 and P0.


     任何控制点  可处理其相应的曲线的曲率。你可以在任何时间改变曲线,通过拖动任意控制点,如下所示:




版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010019717/article/details/47684223

智能推荐

【教程、无技术含量】简单的油猴脚本编写教程_weixin_34191845的博客-程序员宝宝

不建议阅读者:前端大神想要深入学习(涉及到分析挖掘调用网站中js算法/自己写算法)油猴脚本的读者【备注:楼主也不会,楼主也很绝望啊...】阅读以下内容所需知识:javascript/jQuery基础知识【李炎恢的JavaScript教程(http://www.ycku.com/javascript/)(http://www.ycku.com/jquery/)】HTML基础知识【李炎...

Warning:detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd_xiliangMa的博客-程序员宝宝

Warning:detected “cgroupfs” as the Docker cgroup driver. The recommended driver is "systemd问题描述:kubectl init 或者 kubectl join 出现 Warning:detected "cgroupfs" as the Docker cgroup driver. The recommen...

ROS URDF语法-实现小车模型构建-URDF工具使用(十六)_啥也不是的py人的博客-程序员宝宝_svga_vgpu10

1.刷新环境变量只是路径下新建了文件,或者有路径相关的变量修改,只是修改文件编码无需source2.source只是写入内存编译,关机后重开要重新编译3.xml文件中注释也是ctrl+/4.在vscode中ctrl+/就是注释5.evince mycar.pdf是打开pdf的命令

git branch 分支_斜阳雨陌的博客-程序员宝宝_git branch -b

Git自学之路(四)- git branch 分支几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费很多时间。有人把 Git 的分支模型称为它的`‘必杀技特性’’,也正因为这一特性,使得 Git 从

VC++ MapWinGis篇(三)_老狼主的博客-程序员宝宝

添加百度图层(BaiduMapProvider.h):#pragma once#include "BaseProvider.h"#include "BaiduProjection.h"#include &lt;math.h&gt;class BaiduBaseProvider: public BaseProvider{protected: CString Styles;...

[C#] Date类型_王绍全的博客-程序员宝宝_c# date

很多人提出C#需要有个单独的Date类型,以便干净的处理日期。微软的人声称Datetime类型是Date类型的超集,所以没有必要单独的Date类型。但很多人明显并不认可这个答案。下面是我提供的一个Date class实现,给需要的同学:using System;using System.Globalization;using System.Runtime.Serialization;nam

随便推点

大前端进击之路(番外篇)手写Promise_跟兔虫的博客-程序员宝宝_前端的进击

打工人!打工魂!前端才是人上人!此系列总结于大前端进击之路过程中的学习,如果文章中有不对的地方,希望大家能进行批评改正,互相进步。转载请注明出处。手撕Promise源码我们在上一篇大前端进击之路(二)JS异步编程中介绍了Promise,我们不仅要会使用它,也要了解它内部是怎样实现的,让我们的小脑呆瓜子清醒清醒,跟得上我的脚步嘛!1.Promise核心逻辑分析及实现我们首先要知道Promise就是一个类,我们用到这个类的时候,需要传递一个执行器,执行器会立即执行。Promise中有三种..

安装missingno报错_zzh_my的博客-程序员宝宝

missingno可以绘制缺失数据分布图。在安装时报错,信息如下:D:\coding&gt;pip install missingnoDEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be ...

苹果备忘录怎么调字体大小_苹果手机存在备忘录里的内容怎么发给朋友_weixin_39814088的博客-程序员宝宝

苹果手机存在备忘录里的内容怎么发给朋友?我乍一听这个问题,感觉它挺简单的。因为苹果手机备忘录里的内容,是无法直接发给朋友的,只能通过拷贝文字内容,将其复制粘贴给好友。可是上回一个朋友告诉我,他的苹果手机并没有使用自带的备忘录,而是敬业签。朋友告诉我,敬业签是一款手机电脑云同步的备忘录软件,安卓苹果都能同步使用,以后不管换什么手机都不必担忧备忘录导出的问题。他正是因为相中了这一点,才放弃了...

powershell静默批量卸载补丁_qq_34860100的博客-程序员宝宝_powershell删除补丁

#17763.2114 补丁系统KB5005030 (OS Build 17763.2114)$UpdateArray = @(”17763.2114“) foreach ($UpdateVersion in $UpdateArray) { $SearchUpdates = dism /online /get-packages | findstr "Package_for" | findstr "$UpdateVersion" if ($SearchUpdate

No suitable driver found for jdbc:mysql://localhost:3306/stu_mis_Flower195的博客-程序员宝宝

发生这个错误真的很郁闷呀!!好在解决了。参考:http://www.channaly.info/mysql-connectorj-no-suitable-driver-found-for-jdbcmysqllocalhost3306/虽然现还不懂为什么要注册驱动!Mysql connector/J : No suitable driver found for jdbc:my

FastReport调用Delphi中的自定义函数(人民币大写金额)_weixin_30376509的博客-程序员宝宝

人民币大写金额转换函数functionMoneyToCn(ANumberic:Real):string;consts1:string='零壹贰叁肆伍陆柒捌玖';s2:string='分角元拾佰仟万拾佰仟亿拾佰仟万';functionStrTran(constS,s1,s2:string):string;beginResult...

推荐文章

热门文章

相关标签