如何正确的使用Lerp In Unity
摘要
本文探讨如何用lerp实现近似的匀速旋转,当然如果运用本文给出的方法,使用slerp则可以实现匀速旋转,并指出Unity官方lerp示例代码的一些缺陷。
现有问题
比如四元数Lerp API:
Interpolates between a and b by t and normalizes the result afterwards. The parameter t is clamped to the range [0, 1].
public static Quaternion Lerp(Quaternion a, Quaternion b, float t);
以及使用示例
using UnityEngine;
using System.Collections; public class ExampleClass : MonoBehaviour {
public Transform from;
public Transform to;
public float speed = 0.1F;
void Update() {
transform.rotation = Quaternion.Lerp(from.rotation, to.rotation, Time.time * speed);
}
}
如果这样使用,会有如下几个问题值得我们注意:
1)这样的旋转不是匀速的旋转,这种是逐渐减速的旋转。
2)永远无法旋转到目标角度,可以无限的接近。
3)旋转速度与帧数相关,请注意from.rotation在变化,举例来说单位时间内移动2次2%和移动1次4%并不相同。
正确的使用方法
首先可以参考如下文章 如何正确使用lerp
这篇文章的观点和我的观点是一致的,再没看过此文之前,我并不能100%确认我想法的正确性,毕竟示例代码是Unity官方给出的。
实际上,我的项目不是基于Unity,而是基于公司自研的游戏引擎。
我的方法和链接英文提供的方法并不完全相同,以下为示例代码如下:
static f32 GetRotateScale(VEC3 speedDir,VEC3 eulerAngleLast,int dt,f32 rotateSpeed)
{ VEC3 eulerAngleCur = speedDir.getHorizontalAngle();
f32 deltaAngle = ABS(eulerAngleLast.getY() - eulerAngleCur.getY());
deltaAngle = fmod(deltaAngle, 360.f);
if (deltaAngle > 180.f) deltaAngle = 360 - deltaAngle; f32 scale = 1;
if (FLOAT_EQUALS_ZERO_ROUGH(deltaAngle))
scale = 1;
else scale = (dt / 1000.f) * rotateSpeed / deltaAngle;
if (scale > 1)
scale = 1;
return scale;
}
我解释一下函数参数。speeddir是指模型需要朝向的方向,euleranglelast是指当前模型朝向,dt就是deltaTime,rotateSpeed就是指给定的旋转速度。
函数返回值是0-1的比例。该值会传递给lerp做最终的角度旋转。
这个函数功能比较简单,根据角度差,旋转速度来设置scale,当scale等于1时,就会瞬间转到指定角度。每次旋转前需要获取下该次旋转需要的scale。
scale并不是简单的deltaTime * speed 这么简单。
总结
使用slerp可以做到完美的匀速旋转,但是并没有十分必要。实际上采用上述方法采用lerp,肉眼观察已感知不到转速的差异。
1)这是匀速旋转
2)你可以到达目标角度
3)和帧数是无关的
解决问题的方法有很多,每个人都可以有自己的想法。重要的是要先意识到问题的存在。
如何正确的使用Lerp In Unity的更多相关文章
- Unity模型导入的若干问题
原地址:http://tieba.baidu.com/p/2807225555 我觉得有三点感觉在导出时比较重要的1.单位的设置3dsmax系统单位设置就设成厘米显示单位公制也设成厘米这样在max里的 ...
- 使用Unity制作游戏关卡的教程(一)
转自: http://gamerboom.com/archives/74131 作者:Matthias Zarzecki 我正在制作<Looking For Group – The Fork O ...
- HoloLens开发手记 - 入门学习阶段总结
伴随着数月的期待,终于拿到了预订的HoloLens开发者版本套件.随着VR/AR/MR技术的热潮,国内外均对它们的应用与盈利前景持有积极的预期,这也直接导致了国内外当前投资VR/AR/MR技术的热潮. ...
- Unity5.2如何使用VS调试
今天不想使用Mono了,想用VS调试Unity,上百度搜了很久无果,VPN又连不上,结果搞两个小时没搞定.11点终于可以上谷歌了,十分钟搞定.由此可见,百度真的很坑爹...废话不多说下面上正文. 误区 ...
- Unity的Lerp函数实现缓动
在Unity里面Lerp函数可以实现缓动效果 下面例子实现点光源的移动 在场景中创建好一个平面,一个点光源,我在这里随便放了一个模型. 然后新建c#脚本,代码如下: using UnityEngine ...
- unity linear space时 photoshop blend的正确设置
gamma correction的dcc设置 ps在线性空间下工作 blend的时候颜色设置 勾选用灰度系数混合rgb 1.0 这样就是在线性空间下工作了 这样素材在数学上是正确的 r8g8b8a8格 ...
- Unity插值函数Lerp()与增量时间Time.deltatime
一.Unity插值函数Lerp() 通过官方文档简单了解插值函数(https://docs.unity3d.com/ScriptReference/index.html),可以看到插值函数有很多 Ma ...
- a biped was detected but cannot be configured properly (Bipe导入Unity 无法正确识别)
OP stated "I export the biped with 'animation' and 'bake animation' ticked and the correct fram ...
- Unity关于用LoadLevelAdditiveAsync导致新场景的Navmesh数据不正确Loading条的实践
为了解决用Application.LoadLevelAdditiveAsync 导致新场景的Navmesh数据不正确(我们用的是4.63),我们现在loading条做法是先切到Loading的场景,然 ...
随机推荐
- nova分析(3)—— nova-api
nova-api是nova对外提供Restful API的服务,Horizon.novaclient等均通过该api与nova进行通信. nova其实对外提供了多个api服务,包括下面这些服务: no ...
- Python基础教程【读书笔记】 - 2016/7/24
希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴! 第九波:第9章 魔法方法.属性和迭代器 在Python中,有的名称会在前面和后面都加上两个下划线,这种写法很特别.已 ...
- 什么是编解码器codec
编解码器(英语:codec)指的是一个能够对一个信号或者一个数据流进行编解码操作的设备或者程序.这里指的变换既包括将信号或者数据流进行编码(通常是为了传输.存储或者加密)或者提获取到一个编码流的操作, ...
- MySQL key/value存储方案(转)
需求 250M entities, entities表共有2.5亿条记录,当然是分库的. 典型解决方案:RDBMS 问题:由于业务需要不定期更改表结构,但是在2.5亿记录的表上增删字段.修改索引需要锁 ...
- DBA_Oracle DBA常用表汇总(概念)
2014-06-20 Created By BaoXinjian
- jstack使用-倒出线程堆栈
jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使 ...
- 帝国CMS 6.0功能解密之新版结合项功能,帝国结合项使用
可以用来做A-Z信息检索 某字段等于多少,输出 等等 帝国CMS6.0在继承以往版本结合项功能的基础上又新增很多特性,更强大.今天我们就专门来讲解6.0的结合项改进. 回顾下以往版本的结合项语 ...
- struts2请求过程源码分析
Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork的核心,所以,Struts2并不是一个不成熟的产品,相 ...
- js实现未知宽高的元素在指定元素中垂直水平居中
js实现未知宽高的元素在指定元素中垂直水平居中:本章节介绍一下如何实现未知宽高的元素在指定元素下实现垂直水平居中效果,下面就以span元素为例子,介绍一下如何实现span元素在div中实现水平垂直居中 ...
- 定时任务 Crontab命令 详解
crontab是Unix和Linux用于设置周期性被执行的指令,是互联网很常用的技术,很多任务都会设置在crontab循环执行,如果不使用 crontab,那么任务就是常驻程序,这对你的程序要求比较高 ...