周小结2016/8/22-8/28_Bezier
来源:互联网 发布:怎样在淘宝上卖东西 编辑:程序博客网 时间:2024/05/24 04:53
贝塞尔曲线:
项目要求让角色沿着几个点做平滑的移动,研究了下贝塞尔曲线,主要是求连续点的一个算法,知道公式的话,写成代码还是比较简单的,先从简单的入手,方便理解,我们先从俩个点入手,让对象从一个点到另一个点移动,先看代码
using System;using UnityEngine;using System.Collections;[Serializable]public class Bezier{ public Vector3 p0; public Vector3 p1; public Bezier(Vector3 v0, Vector3 v1) { this.p0 = v0; this.p1 = v1; } public Vector3 GetPointAtTime(float t) { Vector3 tmpVector3=Vector3.zero; tmpVector3 = (1 - t) * p0 + t * p1; return tmpVector3; }}using UnityEngine;using System.Collections;using System.Collections.Generic;public class MyBezier : MonoBehaviour{ private Bezier myBezier; public Transform startTransform;//起始位置 public Transform endTransform; //终点位置 private List<Vector3> pothList; //存放中间点 private int index = 0; void Start() { pothList=new List<Vector3>(); myBezier = new Bezier(startTransform.position, endTransform.position); //获取2个点中间的100个路径点 for (int i = 0; i < 100; i++) { Vector3 tmpVector3 = myBezier.GetPointAtTime(0.01f*i); pothList.Add(tmpVector3); } } void FixedUpdate() { int leng = pothList.Count; if (leng > 0 && index < leng) { transform.position = pothList[index]; index++; } }}
这里就用到了贝塞尔曲线的公式
一阶贝塞尔曲线 B(t)=(1-t)P0 + t P1 (t的取值范围是0--1)
如果想让对象平滑的移动,可以将上面的代码用lerp实现
二阶贝塞尔曲线 B(t)=(1-t)2P0+2t(1-t)P1+t2P2,t∈[0,1]
三阶贝塞尔曲线 B(t)=(1-t)3P0+3t(1-t)2P1+3t2(1-t)P2+t3P3,t∈[0,1]
四阶贝塞尔曲线 B(t)=(1-t)4P0+4t(1-t)3P1+4t2(1-t)2P2+4t3(1-t)P3+t4P4,t∈[0,1]
依次类推
例如三阶的代码为了更方便理解,更加直观,可以写成下面的形式
using System;using UnityEngine;using System.Collections;[Serializable]public class Bezier{ public Vector3 p0; public Vector3 p1; public Vector3 p2; public Vector3 p3; public Bezier(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3) { this.p0 = v0; this.p1 = v1; this.p2 = v2; this.p3 = v3; } public Vector3 GetPointAtTime(float t) { Vector3 tmpVector3 = Vector3.zero; tmpVector3 = (1 - t) * (1 - t) * (1 - t) * p0 + 3 * t * (1 - t) * (1 - t) * p1 + 3 * t * t * (1 - t) * p2 + t * t * t * p3; return tmpVector3; }}using UnityEngine;using System.Collections;using System.Collections.Generic;public class MyBezier : MonoBehaviour{ private Bezier myBezier; public Transform p0;//起始位置 public Transform p1; public Transform p2; public Transform p3; //终点位置 private List<Vector3> pothList; //存放中间点 private int index = 0; void Start() { pothList=new List<Vector3>(); myBezier = new Bezier(p0.position,p1.position,p2.position,p3.position); //获取2个点中间的100个路径点 for (int i = 0; i < 100; i++) { Vector3 tmpVector3 = myBezier.GetPointAtTime(0.01f*i); pothList.Add(tmpVector3); } } void FixedUpdate() { int leng = pothList.Count; if (leng > 0 && index < leng) { transform.position = pothList[index]; index++; } }}
进过计算,Bezier脚本可以简化下算法,这样效率会更高,代码如下
using System;using UnityEngine;using System.Collections;[Serializable]public class Bezier{ public Vector3 p0; public Vector3 p1; public Vector3 p2; public Vector3 p3; private float ax; private float ay; private float az; private float bx; private float by; private float bz; private float cx; private float cy; private float cz; public Bezier(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3) { this.p0 = v0; this.p1 = v1; this.p2 = v2; this.p3 = v3; SetConstant(); } public Vector3 GetPointAtTime(float t) { Vector3 tmpVector3 = Vector3.zero; //tmpVector3 = (1 - t) * (1 - t) * (1 - t) * p0 + 3 * t * (1 - t) * (1 - t) * p1 + 3 * t * t * (1 - t) * p2 + t * t * t * p3; float t2 = t * t; float t3 = t * t * t; float x = this.ax * t3 + this.bx * t2 + this.cx * t + p0.x; float y = this.ay * t3 + this.by * t2 + this.cy * t + p0.y; float z = this.az * t3 + this.bz * t2 + this.cz * t + p0.z; return new Vector3(x, y, z); } void SetConstant() { this.ax = p3.x + 3 * p1.x - p0.x - 3 * p2.x; this.ay = p3.y + 3 * p1.y - p0.y - 3 * p2.y; this.az = p3.z + 3 * p1.z - p0.z - 3 * p2.z; this.bx = 3 * (p0.x + p2.x - 2 * p1.x); this.by = 3 * (p0.y + p2.y - 2 * p1.y); this.bz = 3 * (p0.z + p2.z - 2 * p1.z); this.cx = 3 * (p1.x - p0.x); this.cy = 3 * (p1.y - p0.y); this.cz = 3 * (p1.z - p0.z); }}
本周项目: 虚拟小鸟飞翔的项目
小鸟的轨迹大致按贝塞尔曲线飞翔,人为操作的时候不能让鸟偏离曲线太远,限制一个范围,开始做的时候用的纯数学计算,需求比较多,做的比较复杂。后来想到一个好的解决办法,把鸟放在空物体下,让空物体安装曲线飞,然后我们控制鸟和父级的距离来限制它的范围。
需要注意的是,两点之间的距离可能不相同,为了让鸟按我们想要的速度飞,需要将飞行的速度做个处理
timer += Time.fixedDeltaTime; Vector3 currentTarget = resultList[index]; float distance = Vector3.Distance(currentTarget, currentPos); distance = 1/distance; //用来处理不同的距离飞行速度一样快的一个系数 transform.position = Vector3.Slerp(currentPos, resultList[index], currentSpeed * timer * distance); if (Vector3.Distance(transform.position, resultList[index]) < 0.1f) { index++; timer = 0; currentPos = transform.position; //currentPos记录位置用 }
0 0
- 周小结2016/8/22-8/28_Bezier
- 8月22日小结
- 2005.7-8小结
- oracle 学习小结8
- 8月份工作小结
- oracle 学习小结8
- led驱动(小结8)
- buzzer(小结8-4)
- key_printf(小结8-5)
- Django1.8使用小结
- 2016.4.8每日小结
- 8-11学习小结
- 小结 -2017-8-13
- Linux单元小结(8)
- 8月8日小结
- MTK MMI event 小结 8
- Windows核心编程【8】小结
- 7、8月份读书小结
- js点击获取当前li标签的index值
- idea+maven+SSM
- POJ 3352 Road Construction 点双连通分支 -
- 设计模式学习第十三天
- android 通过包名 启动另外一个android应用程序
- 周小结2016/8/22-8/28_Bezier
- x64下vs2013 C++遍历目录下所有文件使用_findnext()调试时中断
- vim插件:显示树形目录插件NERDTree
- 烟花效果
- 错过了,VR BOX就是隔壁老王的了
- Android 2D Xfermode 理解实现特定形状的头像
- jQuery 实现 select模糊查询 反射机制
- DLL注入
- Python实现抓取CSDN热门文章列表