【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的小伙伴会对贝塞尔曲线有更直观的理解.这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝 ...
随机推荐
- <Natural Language Processing with Python>学习笔记二
用Enthought Canopy作图果然方便.昨天频频出现无法识别pylab模块的异常,今天终于搞好了.以下是今天出来的图:
- (中等) POJ 3034 Whac-a-Mole,DP。
Description While visiting a traveling fun fair you suddenly have an urge to break the high score in ...
- Android面试题随笔1
1.如何让一个应用在手机上产生两个或多个图标? 在清单文件中的activity节点下配置如下:[5,7行代码] <activity android:name=".MainActivit ...
- mysql----ERROR 1040 (HY000): Too many connections
http://gwokae.mewggle.com/wordpress/index.php/archives/683 查看最大链接 mysql -h alg-db14 -u bfdroot -pqia ...
- 阿里开源Mysql分布式中间件:Cobar
目前在从事数据库中间件的开发和维护工作,我们使用的数据库中间件就是由cobar改造而来,所以对于cobar的一些说明一看就明白了: 下面是看到的一个很不错的分析文档 这里整理了下方便自己学习使用. C ...
- iOS调试-LLDB学习总结
from:http://www.jianshu.com/p/d6a0a5e39b0e LLDB阐述 LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器.LLDB 绑定在 ...
- jQuery源码学习(2):选择器初窥
选择器初窥 代码架构: jQuery选择器可以依照传入数据的类型分为五大类: 传入字符串:$("div"), $("#id"), $(".div1&q ...
- 为什么建立TCP连接需要三次握手,为什么断开TCP连接需要四次握手,TIME_WAIT状态的意义
为什么建立TCP连接需要三次握手? 原因:为了应对网络中存在的延迟的重复数组的问题 例子: 假设client发起连接的连接请求报文段在网络中没有丢失,而是在某个网络节点长时间滞留了,导致延迟到达ser ...
- 初识Google code jam平台
为了熟悉一下code jam的平台,今天简单试了一下,做了一下Qualification Round Africa 2010的三道题目,都是很基础的. A题:给一个数n和一系列数a[],从a[]中找出 ...
- UVa 990 - Diving for Gold
题目大意:一个潜水者去海底寻找金子,已知有n个有金子的地点,分别给出他们的深度和价值.但是由于潜水者只有一瓶氧气,所以他只能在海底呆有限的时间,问他如何才能在这有限的时间里获得尽可能多的金子,并打印出 ...