如何正确的使用Lerp In Unity
来源:互联网 发布:政府部门数据共享 编辑:程序博客网 时间:2024/05/10 12:34
摘要
本文探讨如何用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中Lerp的使用
- Unity 的 mathf.lerp
- unity Mathf Lerp 的用法
- Using Vector3.Lerp() correctly in Unity
- Unity的Lerp函数实现缓动
- unity中mathf.Lerp的运用
- 【恶搞】如何在Unity正确的使用try-catch
- Unity中Lerp与SmoothDamp函数使用误区浅析
- Unity中Lerp与SmoothDamp函数使用误区浅析
- Unity中的Lerp函数
- Unity Vector3.Lerp
- Unity —— 关于Lerp插值的基本原理
- 如何正确的使用PeekMessage()
- 如何正确的使用PeekMessage()
- 如何正确的使用SharedPreferences?
- 如何正确的使用SharedPreferences?
- 如何正确的使用ButterKnife
- 上传图片前不上传预览?
- zk还能这么玩儿 - 一个域名 解析所有
- 项目中快速搭建Retrofit
- 建议15: 使用dynamic来简化反射实现
- windows config manager
- 如何正确的使用Lerp In Unity
- ArrayList——内存开销,时间上的开销
- 大数据时代,IBM 带你玩转大数据处理
- memcached入门搭建
- Unreal Engine 4 物理模拟之物理碰撞、重叠与射线检测
- Android 自定义虚线段长和点宽
- 对称加密DES和TripleDES
- C语言实现顺序表
- 打怪升级