简单的小球沿贝塞尔曲线运动,适合场景漫游使用

贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自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 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)的更多相关文章

  1. Java_Swing实现小球沿正弦曲线运动的代码

    1 package zuidaimapack_1; import java.awt.*; import javax.swing.*; /** *Java_Swing实现小球沿正弦曲线运动的代码 * @ ...

  2. html5 canvas高级贝塞尔曲线运动动画(好吧这一篇被批的体无完肤!都说看不懂了!没办法加注释了!当然数学不好的我也没办法了,当然这还涉及到一门叫做计算机图形学的学科)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. Unity3d场景漫游---iTween实现

    接触U3D以来,我做过的场景漫游实现方式一般有以下几种: Unity3d中的Animation组件,通过设置摄像机的关键点实现场景漫游 第一人称或第三人称控制器 编写摄像机控制脚本 iTween iT ...

  4. 基于SketchUp和Unity3D的虚拟场景漫游和场景互动

    这是上学期的一次课程作业,难度不高但是也一并记录下来,偷懒地拿课程报告改改发上来. 课程要求:使用sketchUp建模,在Unity3D中实现场景漫游和场景互动. 知识点:建模.官方第一人称控制器.网 ...

  5. unity3d简单的相机跟随及视野旋转缩放

    1.实现相机跟随主角运动 一种简单的方法是把Camera直接拖到Player下面作为Player的子物体,另一种方法是取得Camera与Player的偏移向量,并据此设置Camera位置,便能实现简单 ...

  6. php 简单计算权重的方法(适合抽奖类的应用)

    //简单权重计算器 $data222=array(     0=>array('id'=>1,'name'=>'一等奖','weight'=>'3'),     1=>a ...

  7. Unity3D 简单的倒计时

    using System; using UnityEngine; using System.Collections; public class TimeCountdown : MonoBehaviou ...

  8. Unity3d简单的socket通信

    vs2010或其他创建C#工程 C#端代码一: using System; using System.Collections.Generic; using System.Linq; using Sys ...

  9. egret贝塞尔曲线运动

    class MtwGame { public constructor() { } private static _instance: MtwGame; public static get Instan ...

随机推荐

  1. wpf研究之道——datagrid控件数据绑定

    前台: <DataGrid x:Name="TestCaseDataGrid" ItemsSource="{Binding}" > {binding ...

  2. "双非"应届生校招如何获得大厂青睐?(内附技术岗超全求职攻略)

    写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路.故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有恐惧症的...等将来打算从事技术岗 ...

  3. JAVA 中的 反射

    CLASS类 1) 在面向对象的世界里,万事万物皆对象. 在java中有两样东西不是面向对象 1.普通的数据类型(java中有封装类来弥补它) 2. java中静态的东西 2) 类是对象吗? 类是对象 ...

  4. WPF自定义控件与样式-自定义按钮(Button)

    一.前言 程序界面上的按钮多种多样,常用的就这几种:普通按钮.图标按钮.文字按钮.图片文字混合按钮.本文章记录了不同样式类型的按钮实现方法. 二.固定样式的按钮 固定样式的按钮一般在临时使用时或程序的 ...

  5. JavaScript简单重写构造器的原型

    //简单重写原型对象: //一个构造函数Person function Person(){ } //重写Person的原型 //把Person的原型赋值给一个新的对象 是我们重写的过程 Person. ...

  6. 剑指offer-二叉树的下一个节点

    题目描述   给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针.   解题思路 分情况考虑如下: 若该节点为空,则直 ...

  7. Codeforces Round #436 (Div. 2) B. Polycarp and Letters

    http://codeforces.com/contest/864/problem/B 题意: 给出一个字符串,要求找到一个集合S,使得从S中选出的所有数,在这些数的位置上的字母全部为小写且是不同的字 ...

  8. Struts(九):值栈(OGNL)

    引言 在我们开发过程中,往往会使用一个对像传递到一个具体的action中,之后到跳转页面中访问对应对象的具体的参数. 比如:我们搭建一个struts2项目: 回顾下如何搭建strut2: 1.下载的s ...

  9. [翻译] TensorFlow Programmer's Guide之Frequently Asked Questions(问得频率最多的几个问题)

    目录: 特点和兼容性(Features and Compatibility) 建立一个TensorFlow图(Building a TensorFlow graph) 运行一个TensorFlow计算 ...

  10. JS查找字符串中出现次数最多的字符

    本文给大家带来两种js中查找字符串中出现次数最多的字符,在这两种方法中小编推荐使用第二种,对js查找字符串出现次数的相关知识感兴趣的朋友一起看看吧   在一个字符串中,如 'zhaochucichuz ...