Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

插值

插值是图形编程中的一种常规操作,可以在两个值之间进行混合或过渡。插值还可以让移动、旋转等运动变得平滑。熟悉插值对拓展游戏开发者的视野大有裨益。

基本思想是从 A 转换到 B。t 值是介于两者之间的状态。

举个例子,如果 t 是 0,那么他的状态是 A。如果 t 是 1,那么它的状态是 B。任何介于两者之间的状态都是插值

两个实数(浮点数)之间的插值可以描述为:

interpolation = A * (1 - t) + B * t

通常简化为:

interpolation = A + (B - A) * t

这种以恒定速度将一个值转换为另一个值的插值被称为“线性”。因此,当你听到线性插值时,你就知道他们指的是这个公式。

还有其他类型的插值,这里将不做讨论。建议之后阅读贝塞尔页面。

向量插值

向量类型(Vector2Vector3)也可以插值,向量自带了相关的便捷函数 Vector2.lerp()Vector3.lerp()

对于三次插值,还有 Vector2.cubic_interpolate()Vector3.cubic_interpolate() ,它们执行 Bezier 式插值。

下面是从 A 点插值到 B 点的示例伪代码:

var t = 0.0

func _physics_process(delta):
    t += delta * 0.4

    $Sprite2D.position = $A.position.lerp($B.position, t)

它将产生以下运动:

../../_images/interpolation_vector.gif

变换插值

也可以对整个变换进行插值(确保它们具有均一缩放,或者至少有相同的非均一缩放)。为此,可以使用函数 Transform3D.interpolate_with()

下面是将猴子从位置 1 转换为位置 2 的例子:

../../_images/interpolation_positions.png

使用以下伪代码:

var t = 0.0

func _physics_process(delta):
    t += delta

    $Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)

又会产生下面的动作:

../../_images/interpolation_monkey.gif

平滑运动

插值可用于平滑地跟随一个变化的目标值,例如位置或旋转。每一帧,lerp() 都会将当前值朝着目标值移动,移动量为两者之间剩余差值的一个固定百分比。当前值会平滑地移向目标值,随着距离的接近而逐渐减速。以下是一个使用插值平滑让圆圈跟随鼠标的示例:

const FOLLOW_SPEED = 4.0

func _physics_process(delta):
    var mouse_pos = get_local_mouse_position()

    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, delta * FOLLOW_SPEED)

如下:

../../_images/interpolation_follow.gif

这对平滑相机运动、跟随玩家的盟友(确保他们维持在一定范围内)以及许多其他常见的游戏模式很有用。

备注

尽管使用了 delta,上述公式仍然依赖于帧率,因为 lerp()weight 参数表示剩余差值的一个百分比,而不是一个绝对的变化量。在 _physics_process() 中,这通常没有问题,因为物理引擎预期会保持恒定的帧率,因此 delta 预期会保持不变。

若需要能在 process() 中使用、帧率无关版本的平滑插值,请改用以下公式:

const FOLLOW_SPEED = 4.0

func _process(delta):
    var mouse_pos = get_local_mouse_position()
    var weight = 1 - exp(-FOLLOW_SPEED * delta)
    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, weight)

该公式的推导过程超出了本页的范围。如需解释,请参阅更好的线性插值平滑或观看线性插值平滑真不行