【Unity3d游戏开发】游戏中的贝塞尔曲线以及其在Unity中的实现
RT,马三最近在参与一款足球游戏的开发,其中涉及到足球的各种运动轨迹和路径,比如射门的轨迹,高吊球,香蕉球的轨迹。最早的版本中马三是使用物理引擎加力的方式实现的足球各种运动,后来的版本中使用了根据物理学公式手动计算位置和物体速度的方式实现,现在这个版本中使用的是DoTween+贝塞尔曲线调节来实现。(关于它们之间的各种优缺点我们会在以后单独开一篇博客来探讨,届时也会放出源代码互相学习下)好了,言归正传,今天马三就来和大家一起学习一下游戏中的贝塞尔曲线以及其在Unity中如何实现。
一、简介
贝塞尔曲线是最基本的曲线,一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的河流等。
一条贝塞尔曲线是由一组定义的控制点 P0到 Pn,在 n 调用它的顺序 (n = 1 为线性,2 为二次,等.)。第一个和最后一个控制点总是具有终结点的曲线;然而,中间两个控制点 (如果有的话) 一般不会位于曲线上 。
(1)贝塞尔曲线包含两个控制点即 n = 2 称为线性的贝塞尔曲线
(2)贝塞尔曲线包含三个控制点即 n = 3 称为二次贝塞尔曲线
(3)贝塞尔曲线包含四个控制点即 n = 4,所以称为三次贝塞尔曲线。
贝塞尔曲线返回点的贝塞尔函数,使用线性插值的概念作为基础。
二、公式
1.线性贝塞尔公式:
给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出:

其等同于线性插值。
效果图(文章中部分图片转载自CSDN):

2.二次贝塞尔公式:
二次方贝兹曲线的路径由给定点P0、P1、P2控制,这条线由下式给出:

效果图:

3.三次贝塞尔方程:


4.一般参数形式的贝塞尔方程:
N阶贝兹曲线可如下推断。给定点P0、P1、…、Pn,其贝兹曲线即:

通过两个低阶的贝塞尔曲线插值的堆叠总能够获得更高阶的贝塞尔曲线,通俗的来说通过对两条低阶的贝塞尔曲线插值,你可以求得一条高一阶的贝塞尔曲线。
比如:二次贝塞尔曲线是点对点的两个线性贝塞尔曲线的线性插值,三次贝塞尔曲线是两条二次贝塞尔曲线的线性插值。
三、实现与应用
效果图:


通过调节起始点(左边的白球)、控制点(中间的白球)和结束点(右边的白球)可以获得到不同的贝塞尔曲线,然后使用LineRender组件将路径绘制出来,以方便观察。下面就是实现此功能的代码:
using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(LineRenderer))]
public class Bezier : MonoBehaviour
{
public Transform[] controlPoints;
public LineRenderer lineRenderer; private int layerOrder = ;
private int _segmentNum = ; void Start()
{
if (!lineRenderer)
{
lineRenderer = GetComponent<LineRenderer>();
}
lineRenderer.sortingLayerID = layerOrder;
} void Update()
{ DrawCurve(); } void DrawCurve()
{
for (int i = ; i <= _segmentNum; i++)
{
float t = i / (float)_segmentNum;
int nodeIndex = ;
Vector3 pixel = CalculateCubicBezierPoint(t, controlPoints[nodeIndex].position,
controlPoints[nodeIndex+].position, controlPoints[nodeIndex+].position);
lineRenderer.numPositions = i;
lineRenderer.SetPosition(i - , pixel);
} } Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = - t;
float tt = t * t;
float uu = u * u; Vector3 p = uu * p0;
p += * u * t * p1;
p += tt * p2; return p;
} }
CalculateCubicBezierPoint()函数负责根据T值计算出对应的贝塞尔曲线中的点,DrawCurve()函数通过不断的改变T值,并调用CalculateCubicBezierPoint()获得坐标点,然后通过LineRenderer将这些点绘制出来。
为了使用方便,可以将计算贝赛尔曲线的方法放到一个工具类中——BezierUtils类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class BezierUtils
{
/// <summary>
/// 根据T值,计算贝塞尔曲线上面相对应的点
/// </summary>
/// <param name="t"></param>T值
/// <param name="p0"></param>起始点
/// <param name="p1"></param>控制点
/// <param name="p2"></param>目标点
/// <returns></returns>根据T值计算出来的贝赛尔曲线点
private static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = - t;
float tt = t * t;
float uu = u * u; Vector3 p = uu * p0;
p += * u * t * p1;
p += tt * p2; return p;
} /// <summary>
/// 获取存储贝塞尔曲线点的数组
/// </summary>
/// <param name="startPoint"></param>起始点
/// <param name="controlPoint"></param>控制点
/// <param name="endPoint"></param>目标点
/// <param name="segmentNum"></param>采样点的数量
/// <returns></returns>存储贝塞尔曲线点的数组
public static Vector3 [] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint,int segmentNum)
{
Vector3 [] path = new Vector3[segmentNum];
for (int i = ; i <= segmentNum; i++)
{
float t = i / (float)segmentNum;
Vector3 pixel = CalculateCubicBezierPoint(t, startPoint,
controlPoint, endPoint);
path[i - ] = pixel;
Debug.Log(path[i-]);
}
return path; }
}
通过调用 GetBeizerList( )方法就可以获得到一个包含着计算出的贝塞尔曲线的数组,然后让Obejct沿着数组里面的路径移动就可以模拟出各种曲线运动的效果了,比如炮弹的飞行轨迹,香蕉球、弧圈球等等各种各样的曲线效果了,比如下面的效果图:



博客中贝塞尔曲线工程的开源地址:https://github.com/XINCGer/Unity3DTraining/tree/master/BezierTest
作者:马三小伙儿
出处:http://www.cnblogs.com/msxh/p/6270468.html
请尊重别人的劳动成果,让分享成为一种美德,欢迎转载。另外,文章在表述和代码方面如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!
【Unity3d游戏开发】游戏中的贝塞尔曲线以及其在Unity中的实现的更多相关文章
- Unity3d游戏中自定义贝塞尔曲线编辑器[转]
关于贝塞尔曲线曲线我们再前面的文章提到过<Unity 教程之-在Unity3d中使用贝塞尔曲线>,那么本篇文章我们来深入学习下,并自定义实现贝塞尔曲线编辑器,贝塞尔曲线是最基本的曲线,一般 ...
- NGUI研究院之在Unity中使用贝塞尔曲线(六)[转]
鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是 ...
- 在Unity中使用贝塞尔曲线(转)
鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是 ...
- NGUI研究之在Unity中使用贝塞尔曲线
鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天由于工作的原因须要将贝塞尔曲线加在project中.那么我迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的随意角度的曲线,这两个点一 ...
- svg path中的贝塞尔曲线
首先介绍以下什么是贝塞尔曲线 贝塞尔曲线又叫贝茨曲线(Bezier),由两个端点以及若干个控制点组成,只有两个端点在曲线上,控制点不在曲线上,只是控制曲线的走向. 控制点个数为0时,它是一条直线; 控 ...
- Unity游戏中使用贝塞尔曲线
孙广东 2015.8.15 比方在3D rpg游戏中.我们想设置弹道,不同的轨迹类型! 目的:这篇文章的主要目的是要给你关于在游戏怎样使用贝塞尔曲线的基本想法. 贝塞尔曲线是最主要的曲线,一般用在 ...
- [Android游戏开发]游戏框架的搭建
通常情况下,游戏开发的基本框架中,一般包括以下模块: 窗口管理(Window management):该模块负责在Android平台上创建.运行.暂停.恢复游戏界面等功能. 输入模块(Input):该 ...
- Canvas中绘制贝塞尔曲线
① 什么是贝塞尔曲线? 在数学的数值分析领域中,贝济埃曲线(英语:Bézier curve,亦作“贝塞尔”)是计算机图形学中相当重要的参数曲线.更高维度的广泛化贝济埃曲线就称作贝济埃曲面,其中贝济埃三 ...
- iOS开发之画图板(贝塞尔曲线)
贝塞尔曲线,听着挺牛气一词,不过下面我们在做画图板的时候就用到贝塞尔绘直线,没用到绘制曲线的功能.如果会点PS的小伙伴会对贝塞尔曲线有更直观的理解.这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝 ...
随机推荐
- [iOS]关于零基础学习iOS开发的学习方法总结
关于零基础学习iOS开发的学习方法总结 最近很多零基础来参加蓝鸥培训的学生经常会问到一些学习方法的问题,就如下我自己见过的好的学习方法一起讨论一下. 蓝鸥iOS开发技术的学习路线图 程序员的主要工作是 ...
- PAT (Advanced Level) 1005. Spell It Right (20)
简单题. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> ...
- iOS中"查看更多/收起"功能实现
实现效果如图: 查看更多功能在很多app种都有应用,在这里简单的实现,介绍实现流程: 一个tableViewCell中包含一个collectionView,"查看更多"按钮是tab ...
- JAVA调用c/c++代码
JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱 ...
- Python+Selenium定位不到元素常见原因及解决办法(报:NoSuchElementException)
在做web应用的自动化测试时,定位元素是必不可少的,这个过程经常会碰到定位不到元素的情况(报selenium.common.exceptions.NoSuchElementException ...
- Codeforces#363 Div2
A题: 题意:给定一些数,给定一些往左走和往右走的操作,问是否能够相遇,如果相遇请求出相遇时间 分析:对于相邻两个数,如果大的往左,小的往右就能够相遇,否则不能相遇,在求出所有相遇当中的第一次相遇即可 ...
- (译)Windsor入门教程---第五部分 添加日志功能
介绍 现在我们已经有了基础的框架了,是时候添加内容了,那么我们首先应该考虑的就是在应用程序中添加日志功能.我们会使用Windsor来配置,在这一部分,你将学习Windsor之外的其他功能. L ...
- HYBControllerTransitions中文文档
中文文档 HYBControllerTransitions是自定义围场动画API封装类库,使用简便.使用者不需要了解太多转场动画知识,即可轻松接入项目使用. 这是一个给开发者们提供自定义push.po ...
- mysql管理---表分区
一.什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了. 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分 ...
- 使用LIBUSB实现和自定义通讯设备通讯--MFC代码在末尾
LIBUSB是一款简单好用的USB通讯开发库,一般HID设备用该库通讯能大大降低开发周期,使用如下,首先需要为设备安装驱动 在libusb的bin目录下有一个inf_wirzed.exe的文件,该文件 ...