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

贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自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. js 中bind

    function fn(a){ this.innerHTML = a; console.log(this); } //fn("hello"); span1.onclick =fun ...

  2. 从PRISM开始学WPF(八)導航Navigation?

    0x6Navigation Basic Navigation Prism中的Navigation提供了一种类似导航的功能,他可以根据用户的输入,来刷新UI. 先看一个最简单的例子,通过按钮来导航到一个 ...

  3. [UWP]针对UWP程序多语言支持的总结,含RTL

    UWP 对 Globalization and localization 的支持非常好,可以非常容易地实现应用程序本地化. 所谓本地化,表现最为直观的就是UI上文字和布局方式了,针对文字,提供不同的语 ...

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

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

  5. Docker Mysql主从同步配置搭建

    Docker Mysql主从同步配置搭建 建立目录 在虚拟机中建立目录,例如路径/home/mysql/master/data,目录结构如下: Linux中 新建文件夹命令:mkdir 文件夹名 返回 ...

  6. 返回到前台的String出现乱码问题

    使用springmvc给前天返回String类型的数据出现乱码问题可以在配置环境Spring-mvc.xml中添加如下代码 <mvc:annotation-driven> <mvc: ...

  7. 记一次将公司网站http换成https

    看了博客园将近一年了,一直都只是在被动的看,总觉得应该写点什么,但是又不知道该写点什么.今天正好公司要把网站由http换成https,那我就顺便记录一下吧. 由于之前没有弄过,所以就面向百度编程. 首 ...

  8. C#实现导出Excel

    这段时间用到了导出Excel的功能,这个功能还是比较常用的,我常用的有两个方法,现在整理一下,方便以后查看. 一.实现DataTable数据导出到本地,需要自己传进去导出的路径. /// <su ...

  9. 微信小程序授权获取用户详细信息openid

    小程序获取用户的头像昵称openid之类 第一种使用wx.getUserInfo直接获取微信头像,昵称 wx.getUserInfo({ success: function (res) { that. ...

  10. 【原生js实现一键回到顶部】

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...