Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)
简单的小球沿贝塞尔曲线运动,适合场景漫游使用
贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自http://blog.csdn.net/u010019717/article/details/47684223 。仅供学习,知识分享。如有侵权,联系删除。)
贝塞尔曲线是最基本的曲线,一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的河流等。
一条贝塞尔曲线是由一组定义的控制点 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 的贝塞尔曲线(就是高级的是两个低一级的线性插值)。
以下是本人所写。
Hierarchy视图如下:

效果如下动画所示:

脚本如下:(脚本挂载在场景中任意对象上)
using System.Collections;
using System.Collections.Generic;
using UnityEngine; //实现代码如下:(最外层有6个点,依次5,4,3,2,1)
//添加一个小球,沿曲线运动,使小球看向目标物体
public class Test_DrawLine : MonoBehaviour { [SerializeField] private Transform points; //控制点父对象
private List<Transform> point_tranList = new List<Transform>(); //控制点列表
[SerializeField] private int pointCount = ; //曲线点的个数
private List<Vector3> line_pointList; //曲线点列表 [SerializeField] private Transform lookTarget; //看向目标
[SerializeField] private GameObject ball; //运动物体
[SerializeField] private float time0 = ; //曲线点之间移动时间间隔
private float timer = ; //计时器
private int item = ; //曲线点的索引
private bool isTrue = false; //使小球沿曲线运动
//这里不能直接在for里以Point使用差值运算,看不到小球运算效果
//定义一个计时器,在相隔时间内进行一次差值运算。
void Awake()
{
Init();
}
void Init()
{
if (null != points && point_tranList.Count == )
{
foreach (Transform item in points)
{
point_tranList.Add(item);
}
}
line_pointList = new List<Vector3>();
for (int i = ; point_tranList.Count != && i < pointCount; i++)
{
//一
Vector3 pos1 = Vector3.Lerp(point_tranList[].position, point_tranList[].position, i / (float)pointCount);
Vector3 pos2 = Vector3.Lerp(point_tranList[].position, point_tranList[].position, i / (float)pointCount);
Vector3 pos3 = Vector3.Lerp(point_tranList[].position, point_tranList[].position, i / (float)pointCount);
Vector3 pos4 = Vector3.Lerp(point_tranList[].position, point_tranList[].position, i / (float)pointCount);
Vector3 pos5 = Vector3.Lerp(point_tranList[].position, point_tranList[].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);
}
if (line_pointList.Count == pointCount)
isTrue = true;
} void Update()
{
if (!isTrue)
return;
timer += Time.deltaTime;
if (timer > time0)
{
timer = ;
if(item >= line_pointList.Count-)
{
ball.transform.LookAt(line_pointList[item]);
}
else
{
if (lookTarget)
ball.transform.LookAt(lookTarget);
else
ball.transform.LookAt(line_pointList[item]);
}
ball.transform.localPosition = Vector3.Lerp(line_pointList[item - ], line_pointList[item], 1f);
item++;
if (item >= line_pointList.Count)
item = ;
}
} //------------------------------------------------------------------------------
//在scene视图显示
void OnDrawGizmos()//画线
{
Init();
Gizmos.color = Color.yellow;
for (int i = ; i < line_pointList.Count - ; i++)
{
Gizmos.DrawLine(line_pointList[i], line_pointList[i + ]);
}
} }
Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)的更多相关文章
- Java_Swing实现小球沿正弦曲线运动的代码
1 package zuidaimapack_1; import java.awt.*; import javax.swing.*; /** *Java_Swing实现小球沿正弦曲线运动的代码 * @ ...
- html5 canvas高级贝塞尔曲线运动动画(好吧这一篇被批的体无完肤!都说看不懂了!没办法加注释了!当然数学不好的我也没办法了,当然这还涉及到一门叫做计算机图形学的学科)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Unity3d场景漫游---iTween实现
接触U3D以来,我做过的场景漫游实现方式一般有以下几种: Unity3d中的Animation组件,通过设置摄像机的关键点实现场景漫游 第一人称或第三人称控制器 编写摄像机控制脚本 iTween iT ...
- 基于SketchUp和Unity3D的虚拟场景漫游和场景互动
这是上学期的一次课程作业,难度不高但是也一并记录下来,偷懒地拿课程报告改改发上来. 课程要求:使用sketchUp建模,在Unity3D中实现场景漫游和场景互动. 知识点:建模.官方第一人称控制器.网 ...
- unity3d简单的相机跟随及视野旋转缩放
1.实现相机跟随主角运动 一种简单的方法是把Camera直接拖到Player下面作为Player的子物体,另一种方法是取得Camera与Player的偏移向量,并据此设置Camera位置,便能实现简单 ...
- php 简单计算权重的方法(适合抽奖类的应用)
//简单权重计算器 $data222=array( 0=>array('id'=>1,'name'=>'一等奖','weight'=>'3'), 1=>a ...
- Unity3D 简单的倒计时
using System; using UnityEngine; using System.Collections; public class TimeCountdown : MonoBehaviou ...
- Unity3d简单的socket通信
vs2010或其他创建C#工程 C#端代码一: using System; using System.Collections.Generic; using System.Linq; using Sys ...
- egret贝塞尔曲线运动
class MtwGame { public constructor() { } private static _instance: MtwGame; public static get Instan ...
随机推荐
- rsync 自动创建目录的坑点
rsync同步文件有三种模式: 1.把源站路径下某个文件,同步到目标路径.例如rsync -aR /data/1/2/3/a.txt 1.1.1.1:/data/ ,目标机器将自动创建多层目录存放a. ...
- web api 如何通过接收文件流的方式,接收客户端及前端上传的文件
服务端接收文件流代码: public async Task<HttpResponseMessage> ReceiveFileByStream() { var stream = HttpCo ...
- URL编码和Base64编码 (转)
我们经常会遇到所谓的URL编码(也叫百分号编码)和Base64编码. 先说一下Bsae64编码.BASE64编码是一种常用的将二进制数据转换为64个可打印字符的编码,常用于在通常处理文本数据 ...
- SpringCloud的Config:ConfigServer注册到EurekaServer中,变成一个Eureka服务
一.概念与定义 1.将SpringCloud ConfigServer注册到 EurekaServer,以便ConfigClient以服务的方式引用ConfigServer 2.客户端不再引用 Con ...
- Linux CentOS7.0 (02)修改主机名和ip地址
一.主机名修改 1.查看命令 在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty). "静态"主机名也称为内核主机名 ...
- 使用 Angular CLI 和 Webpack 分析包尺寸
使用 Angular CLI 和 Webpack 分析包尺寸 对于 Web app 来说,高性能总是最高优先级,对于 Angular 也不例外.但是随着应用复杂度的不断增长,我们如何才能知道哪些内容打 ...
- PHP / Laravel 月刊 #23
最新资讯 Laravel 5.6 中文文档翻译完成,译者 60 人,耗时 10 天 Summer Dingo API 中文文档翻译召集[已完成] Summer 我最喜欢 Laravel 5.6 的三个 ...
- python CSS
CSS 一. css的四种引入方式 1.行内式 2.嵌入式 3. 链接式 将一个.css文件引入到HTML文件中 1 <link href="mystyle.css" ...
- vi和vim编辑器
VI vi是一种计算机文本编辑器,由美国计算机科学家比尔·乔伊(Bill Joy)完成编写,并于1976年以BSD协议授权发布. VIM Vim是从vi发展出来的一个文本编辑器.其代码补完.编译及错误 ...
- Android P新功能特性抢先看
2018年3月8日,Google推出了Android P Preview版本,并提供官方镜像下载. 为了让广大开发者能够及时了解Android P的新功能特性,提前为您的app进行良好适配,WeTes ...