Unity中Lerp与SmoothDamp函数使用误区浅析
来源:互联网 发布:linux suse 11安装yum 编辑:程序博客网 时间:2024/05/16 14:29
写在前面
Unity的Lerp和SmoothDamp这两个函数我们在处理物体移动、一些渐进变化或者摄像机的跟随等场景会较常用到,虽然Mathf、Vector2、Vector3等都有这两个函数,但用法上是基本一样的,用起来也比较简单。不过在实际的运用中,往往一不小心却会掉进坑里,下面我们一起来分析一下。
Lerp函数
Lerp函数使用的最常见的误区是把线性移动用成了弹性移动(关键是自己还不知道,还奇怪,咦,不是说好的线性移动吗?怎么有点弹性的赶脚……),如下图所示:
这样子的代码一般是这么写的:
这个错误主要是没有理解好Lerp的第三个参数t的作用,这里我们为了便于理解,我们拿Mathf.Lerp函数来分析,思路是一样的。我们先来看一下Mathf.Lerp函数的具体实现:
估计大家一看函数的实现就明白了关键点,想要线性移动,应该只控制t的变化,t的值在0-1,它就类似一个百分比的值,代表着a点到b点之间的位置,比如想要到a和b之间的3/10的位置,t就应该是0.3,想要一步到位t的值就应该为1。在上述错误的用法中,实际的效果就是第一次到达1/10位置,第二次到达1/10+9/10*1/10的位置……理论上讲永远到不了b点,每一次都是a与b点之间的1/10的位置,所以移动的幅度越来越小,有一种弹性感觉。正确的使用方法如下:
效果如下:
SmoothDamp函数
SmoothDamp函数在使用过程中比较容易出现的一个问题就是容易在代码较复杂的情形下将currentVelocity这个参数需要的变量定义为局部变量,如下:
使用局部变量的效果如下图所示,越来越慢,定义的平滑时间明明是0.3f,怎么用了10几秒的时间都还在缓慢移动?
为了便于理解,我们来看一下Mathf.SmoothDamp的具体实现:
通过具体的实现我们就可以很清楚的发现,currentVelocity这个变量是先使用,然后再赋值,通过ref传递就是为了获取到上一次计算得到的速度值,如果我们使用局部变量,每一次速度都是零,相当于刚开始进行平滑移动,平滑的距离(transform.position到target)不断在缩短,然而平滑时间却没有变化,为了保证大约在平滑的时间内完成平滑移动,这个起步速度肯定是越来越慢的,所以就导致了上图中的问题。
我们把currentVelocity改为全局变量,就可以看到正常效果了
效果如下:
写在最后
好了,以上就是这一次想要和大家一起讨论的内容了,希望对大家有那么一丢丢的帮助。
Unity的Lerp和SmoothDamp这两个函数我们在处理物体移动、一些渐进变化或者摄像机的跟随等场景会较常用到,虽然Mathf、Vector2、Vector3等都有这两个函数,但用法上是基本一样的,用起来也比较简单。不过在实际的运用中,往往一不小心却会掉进坑里,下面我们一起来分析一下。
Lerp函数
Lerp函数使用的最常见的误区是把线性移动用成了弹性移动(关键是自己还不知道,还奇怪,咦,不是说好的线性移动吗?怎么有点弹性的赶脚……),如下图所示:
这样子的代码一般是这么写的:
private Vector3 target = new Vector3(0, 0, 5); void Update() { transform.position = Vector3.Lerp(transform.position, target, 0.1f); }
这个错误主要是没有理解好Lerp的第三个参数t的作用,这里我们为了便于理解,我们拿Mathf.Lerp函数来分析,思路是一样的。我们先来看一下Mathf.Lerp函数的具体实现:
/// <summary>/// <para>Clamps value between 0 and 1 and returns value.</para>/// </summary>/// <param name="value"></param>public static float Clamp01(float value){ float result; if (value < 0f) { result = 0f; } else if (value > 1f) { result = 1f; } else { result = value; } return result;} /// <summary>/// <para>Linearly interpolates between a and b by t.</para>/// </summary>/// <param name="a">The start value.</param>/// <param name="b">The end value.</param>/// <param name="t">The interpolation value between the two floats.</param>/// <returns>/// <para>The interpolated float result between the two float values.</para>/// </returns>public static float Lerp(float a, float b, float t){ return a + (b - a) * Mathf.Clamp01(t);}
private Vector3 target = new Vector3(0, 0, 5);private Vector3 startPos;private float t1; void Start(){ startPos = transform.position;} void Update(){ t1 += 1f * Time.deltaTime; transform.position = Vector3.Lerp(startPos, target, t1);}
SmoothDamp函数
SmoothDamp函数在使用过程中比较容易出现的一个问题就是容易在代码较复杂的情形下将currentVelocity这个参数需要的变量定义为局部变量,如下:
private Vector3 target = new Vector3(0, 0, 5); public float smoothTime = 0.3F; void Update() { Vector3 velocity = Vector3.zero; transform.position = Vector3.SmoothDamp(transform.position, target, ref velocity, smoothTime); } }
为了便于理解,我们来看一下Mathf.SmoothDamp的具体实现:
public static float SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime, [DefaultValue("Mathf.Infinity")] float maxSpeed, [DefaultValue("Time.deltaTime")] float deltaTime) { smoothTime = Mathf.Max(0.0001f, smoothTime); float num = 2f / smoothTime; float num2 = num * deltaTime; float num3 = 1f / (1f + num2 + 0.48f * num2 * num2 + 0.235f * num2 * num2 * num2); float num4 = current - target; float num5 = target; float num6 = maxSpeed * smoothTime; num4 = Mathf.Clamp(num4, -num6, num6); target = current - num4; float num7 = (currentVelocity + num * num4) * deltaTime; currentVelocity = (currentVelocity - num * num7) * num3; float num8 = target + (num4 + num7) * num3; if (num5 - current > 0f == num8 > num5) { num8 = num5; currentVelocity = (num8 - num5) / deltaTime; } return num8; }
通过具体的实现我们就可以很清楚的发现,currentVelocity这个变量是先使用,然后再赋值,通过ref传递就是为了获取到上一次计算得到的速度值,如果我们使用局部变量,每一次速度都是零,相当于刚开始进行平滑移动,平滑的距离(transform.position到target)不断在缩短,然而平滑时间却没有变化,为了保证大约在平滑的时间内完成平滑移动,这个起步速度肯定是越来越慢的,所以就导致了上图中的问题。
我们把currentVelocity改为全局变量,就可以看到正常效果了
private Vector3 target = new Vector3(0, 0, 5); public float smoothTime = 0.3F; private Vector3 velocity = Vector3.zero; void Update() { transform.position = Vector3.SmoothDamp(transform.position, target, ref velocity, smoothTime); }
效果如下:
写在最后
好了,以上就是这一次想要和大家一起讨论的内容了,希望对大家有那么一丢丢的帮助。
本文工程文件(Unity2017.2.0f3):
链接:https://pan.baidu.com/s/1kV7rd4b 密码:vft2
阅读全文
0 0
- Unity中Lerp与SmoothDamp函数使用误区浅析
- Unity中Lerp与SmoothDamp函数使用误区浅析
- SmoothDamp与Lerp函数使用问题误区浅析
- unity中Mathf.Lerp、Mathf.MoveTowards、Mathf.SmoothStep、Mathf.SmoothDamp的区别
- unity中Lerp的使用
- Unity中的Lerp函数
- Unity3D中Mathf.SmoothDamp函数使用与Mathf 数学运算(C#)
- Unity的Lerp函数实现缓动
- unity中mathf.Lerp的运用
- 如何正确的使用Lerp In Unity
- unity3d中的Mathf.SmoothDamp函数的使用学习笔记!!
- Unity Vector3.Lerp()与Vecotr3.MoveTowards()方法区别
- Unity 的 mathf.lerp
- Unity Vector3.Lerp
- Unity中SmoothDamp 平滑阻尼--相机跟随角色移动的示例
- unity Mathf Lerp 的用法
- unity 关于Rotation和Quaternion的一些问题(欧拉角与四元数,lerp与slerp)
- 简述unity中material.color及Color.Lerp线性插值的用法
- Linux防火墙(Iptables)的开启与关闭
- 投色子 游戏
- 如果新能源汽车占领市场,加油站还有未来吗?
- HTML CSS 随笔记之 float
- 数据库前台提示成功,实际后台为成功的问题
- Unity中Lerp与SmoothDamp函数使用误区浅析
- 使用VMware给虚拟机安装linux系统
- c++编写: 检测试笔记本电池充电状况
- SpringMVC从入门到精通(一)
- 注意VC的内存使用,栈变量不可放在全局容器
- 第30章 OpenWrt实现pppoe上网
- HDU5314 Happy King
- SpringMVC从入门到精通(二)
- Java邮件发送详解