matlab的damp返回参数,unity中的差值函数Lerp和SmoothDamp解析(一)

前言

相信做unity的同学或多或少都会有对数值变化进行平滑的需求,比如摄像机的移动,物体颜色的渐变等等,我们不想变化太突然,想让变化过度自然,这个时候我们很自然的会用到Lerp()函数或者SmoothDamp()函数(当然用协程也可以实现),但是我最初使用这两个函数的时候,用出来是这个效果,但是确实不是很理解里面参数所代表的意义,后面还是花了一点点的时间才彻底的清楚这个函数的用法,在这篇文章里我会尝试清晰的把这两个函数一次性讲清楚。(不得不吐槽一下,unity官方文档最初对Lerp函数用法的示例!将Time.deltatime加入第三个参数太不利于理解了!)

1.Lerp解析

1.1Lerp原型以及文字释义

在unityAPI中有各种各样的Lerp可供选择什么Color.Lerp,Vector2.Lerp,Vector3.Lerp等等,网上有些教程把他们一个个拿出来解释,我觉得真的是毫无意义的,最关键的只需要理解其中的一个Lerp就足够了,其它Lerp只是针对它的每一个属性去做变化而已,本质是一样的。

那就是Mathf.Lerp()

//a:变化的起始值

//b:变化的目标值

//t:本次调用返回值所占b和a的差值的比例

//返回值为一个float类型

public static float Lerp(float a, float b, float t);

1.2Lerp初体验

我们拿到一个函数,按照常理去理解,应该调用一次就ok了,效果就出来了,那么我们就在Start()里面调用一次试一下

float origin_X = 0;//起始X坐标

float destination_X = 10;

// Use this for initialization

void Start()

{

//修改正方体在x轴上面的位移

Vector3 startPos = transform.position;

startPos.x = Mathf.Lerp(origin_X, destination_X, 0.1f);

transform.position = startPos;

}

效果如下,其中蓝色的正方体所在坐标为(0,0,0),红色正方体所在坐标为(10,0,0)

e5b06b7be721

运行结果.png

我们会发现白色正方体所在的位置变为了(1,0,0),刚好就是起始点x:0和

终点x:10的十分之一,也是刚好是Math.Lerp()的第三个参数0.1。所以这很直观的让我们知道了第三个参数表征的是什么

第三个参数表征的是,函数的返回值占前两个参数插值的比例,附上网上流传的Lerp实现源码大家就会发现是真的简洁明了

public static float Lerp(float a, float b, float t){

return (b-a)*t;

}

1.3Lerp的用法

根据1.2我们可以知道一件事,想要实现平滑的效果,调用一次Lerp是不行的,因此我们需要在多次调用,巧妙的修改输入的参数,才能得到我们想要的效果。

1.3.1第一种用法(也是unity早期对Lerp的示例用法)

这种用法会多次调用修改第一个参数的值,接下来我们修改一下代码,将Lerp放在Update()里面运行

float origin_X = 0;//起始X坐标

float destination_X = 10;

// Update is called once per frame

void Update()

{

//修改正方体在x轴上面的位移

Vector3 startPos = transform.position;

startPos.x = Mathf.Lerp(origin_X, destination_X, 0.1f);

transform.position = startPos;

}

输入代码后点击运行,恐怖的事情发生了!!!我们会发现白色正方体一直在(1,0,0)的位置。检查一下代码发现,我们传入的参数三个值是恒定的,所以每次返回值都是一样的,因此我们每一帧更新白色正方体的position都会是(1,0,0)。这个时候我们只需要做一件事情,就可以让白色方块从(0,0,0)平滑的运动到(10,0,0),那就是将第一个参数改为自身在当前帧的X坐标,这样一来我们每一帧计算得到的X值都会成为下一帧计算的第一个参数,效果如下。

e5b06b7be721

LerpTest.gif

嗯,so far so good,right?这样去使用的意思是,我们每一帧去移动当前位置距离目标位置的十分之一,也就是

第一帧:移动到当前位置(0,0,0)到(10,0,0)的十分之一,也就是(1,0,0)

第二帧:移动到当前位置(1,0,0)到(10,0,0)的十分之一,也就是(1.9,0,0)

第二帧:移动到当前位置(1.9,0,0)到(10,0,0)的十分之一,也就是(2.71,0,0)

后面以此类推......

我们可以很直观的看到,这样子的变化是非线性的(网上有人说Lerp函数的平滑是非线性的,我认为有失偏颇,只能说在这种用法之下,它的变化是非线性的),其次很关键的一点是,像这样子运动,物体永远都到不了你想去的地方,只能无限的去逼近!

e5b06b7be721

逼死强迫症.png

这就很坑爹了,很多时候我们想得到变化结束的回调,然后判断

if(position.x==10){TODO......}

然后你发现,这条等式永远不成立,一直是9.9999999,真的急skr人,虽然去我们可以把条件改为

if(position.x>=9.9999999){TODO......}

但这也太......丑了,所以如果我们不想代码那么丑,又想让我们的变化是线性变化的话,就可以采用下面第二种方法。

1.3.2第二种用法(unity现在对Lerp的示例用法)

第二种方法是通过每一帧去改变第三个参数的值,让第三个值从0逐渐变化到1,也就可以实现平滑,并且可以准确的知道变化结束的那一刻了。我这里给出一种最为简单的实现。

float origin_X = 0;//起始X坐标

float destination_X = 10;

float t = 0;//每帧增加的插值

// Update is called once per frame

void Update()

{

t += Time.deltaTime;

//修改正方体在x轴上面的位移

Vector3 startPos = transform.position;

startPos.x = Mathf.Lerp(origin_X, destination_X, t);

transform.position = startPos;

}

e5b06b7be721

Lerp2Test.gif

其中t每一帧去累加Time.deltaTime,所以从Update第一次调用开始,到1秒的时候t就会变为1,白色方块就会到达终点,所以方块的变化轨迹这时就由t的变化轨迹确定了,在这里t的变化轨迹基本是匀速运动,所以白块也就匀速的从(0,0,0)点运动到(10,0,0)点。

所以在这种情况下很好的可以判断运动什么时候结束,只需要判断t的值是否大于等于1就可以了

if(t>=1){ TODO...... }

最后

本来想简洁明了的解释清楚这个函数,结果还是写了那么多......看来还是要好好锻炼自己对重点的提炼能力了,其中有什么疑惑或者不认同的地方欢迎大家留言!这周末浪的时间太多了,没有写完SmoothDamp的解释,只能下周再更了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值