关于 unity3d:Lerp with Time.deltaTime

Lerp with Time.deltaTime

我有一个关于 Lerp 的问题。所以我知道 lerp 可以帮助您移动对象,例如:

1
2
3
void update(){
transform.position = vector3.lerp(start.position,end.position, (Time.time / 1000));
}

这将使您的对象到达您的终点。
但是如果你有这个代码:

1
2
3
4
5
6
void Update(){

    transform.position = Vector3.Lerp(transform.position,
                                      destination.position,
                                      speed * 3.0f * Time.deltaTime);
}

你的物体怎么可能到达你的目的地,lerp的第3个参数必须慢慢地达到1,这样你的物体才能到达你的目的地。但是 "speed" , "3.0" , "Time.deltaTime" 总是一样的,那么你的对象怎么可能到达你的目的地呢?

所以最大的问题是:是否有可能对一些变量进行 lerp,这些变量总是具有相同的值并且使用 Time.deltaTime?

现在,由于不同的评论等。我不知道 lerp 是如何工作的,我有可能:

1.) 首先我认为它是这样工作的:

Vector3.lerp(a,b,c)
c 值必须改变每一帧才能移动对象。如果 c 值为 0.2,则您的对象将移动 20%,如果 c 值不改变,则对象将始终移动 20%。因此,要让对象流畅地移动,您的 c 值必须在每一帧都稍微改变一下,这样您的 c 值将从 0 变为 1,您的对象从起点到终点也是如此。

还是这样

2.) 由于有几条评论,我认为 lerp 像这样工作

就像评论说的那样,c 值不必改变值,因为如果你有 c = 0.2 你将通过 20% 的方式和下一帧,如果 c 仍然是 0.2 你将通过 20剩余方式的 % 等等。

那么 lerp 是像 1 那样工作(你必须改变 c)还是像 2 那样工作(你不必改变 c)


变换位置和目标之间的距离呈指数衰减。距离每帧缩小(1 - 速度)(假设速度小于 1)。假设您的游戏应该以 60FPS 运行。如果出于某种原因帧速率下降到 30FPS,则 deltaTime 将增加两倍,并且您应该执行 Lerp 2 次。在这种情况下,距离将收缩 (1 - speed) 然后 (1 - speed) 再次产生 (1 - speed)^2 收缩的结果。由此,您可以概括距离的收缩量为 (1 - speed) ^ (deltaTime / baseDeltaTime),其中 baseDeltaTime 是游戏应该运行的 deltaTime,即 1/60(对于 60FPS)。
输入代码:

1
transform.position = Vector3.Lerp(transform.position, destination.position, 1 - Mathf.Pow(1 - speed * 3.0f, Time.deltaTime * 60));

我猜你不明白 lerp 是如何统一工作的。我会向您推荐 Robbert 的这篇文章如何像专业人士一样 Lerp。

I see this sort of thing far too often:

transform.position = Vector3.Lerp(startPos, endPos, Time.deltaTime);

The person posting it is usually convinced that Vector3.Lerp is
a€?brokena€?, but the real problem is that theya€?re not using it correctly.

Lerp, short for a€?linear interpolationa€? does one very simple thing:
given two values, x and y, it returns a value that is t percent
between them. If you expect the output to change, the arguments you
pass in need to reflect that!

In the example above, it doesna€?t make sense to just pass in
Time.deltaTime, because thata€?s only the time that passed during the
most recent frame. If your game is running at a constant 50fps, thata€?s
always going to be 0.02.


物体到达目标是因为你的起始位置是当前位置,在 lerp 之后,你将物体的位置设置为 Lerp 的结果位置。如果您将起始位置更改为正常的 Vector3,它会 Lerp 到"speed * Time.deltaTime * 3f"


(参见 https://gamedev.stackexchange.com/questions/149103/why-use-time-deltatime-in-lerping-functions)

Lerp有两种常用的使用方式:

1。开始和结束之间的线性混合

1
2
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);

2。朝向目标的指数轻松度

1
current = Mathf.Lerp(current, target, sharpnessPerTick);

请注意,在此版本中,current 值同时显示为输出和输入。它取代了 start 变量,所以我们总是从上次更新时移动到的地方开始。这就是为这个版本的 Lerp 提供从一帧到下一帧的内存的原因。然后,我们从这个移动的起点向 sharpness 参数指定的 target 移动一小部分距离。

这个参数不再是一个"速度",因为我们以类似 Zeno 的方式接近目标。如果 sharpnessPerTick0.5,那么在第一次更新时,我们将实现目标的一半。然后在下一次更新中,我们将移动剩余距离的一半(即初始距离的四分之一)。然后在下一个我们会再次移动一半......

这给出了一个"指数缓动",当远离目标时运动很快,随着渐近接近而逐渐减慢(尽管对于无限精度数,它永远不会在任何有限次数的更新中达到它 - 因为我们的目的它已经足够接近了)。它非常适合追踪移动目标值,或使用"指数移动平均线"平滑噪声输入,通常使用非常小的 sharpnessPerTick 参数,例如 0.1 或更小。


1
myLocation = Mathf.Lerp(myLocation, myDestination, 0.02)

如果您将 Lerp 函数的返回值存储到一个变量中,然后还使用该变量作为同一 Lerp 函数中的最小值,那么每次函数执行时最小值都会越来越大调用。

所以,即使你没有改变 T,你也在改变起始值,因此,存储的值越来越接近最大值。

它最初会非常快地加速,然后随着接近最大值而减速。此外,最大值永远不会达到或需要很长时间。