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.

插值

Interpolation is a common operation in graphics programming, which is used to blend or transition between two values. Interpolation can also be used to smooth movement, rotation, etc. It's good to become familiar with it in order to expand your horizons as a game developer.

基本思想是從 A 轉換到 B。t 值是介於兩者之間的狀態。

舉個例子, 如果 t 值為0, 那麼狀態是A. 如果 t 值是1, 狀態是B. 任何介於兩者之間的都是 插值.

在兩個實數(浮點數)之間, 一個簡單的插值通常描述為:

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

通常簡化為:

interpolation = A + (B - A) * t

這型別的插值名字, 將一個值以 恒定速度 轉換成另一個值 "線性". 當你聽說線性插值時, 就知道他們是指這個簡單的公式.

還有其他型別的插值, 這裡將不做討論. 建議之後閱讀 Bezier 頁面.

向量插值

向量型別 (Vector2Vector3) 也可以插值, 它們提供了方便的函式來實作這一點 Vector2.linear_interpolate()Vector3.linear_interpolate().

對於三次插值,還有 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

變換插值

也可以對整個變換進行插值(確保它們有均勻的縮放,或者至少有相同的非均勻縮放)。對此,可以使用函式 Transform.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

平滑運動

Interpolation can be used to smoothly follow a moving target value, such as a position or a rotation. Each frame, lerp() moves the current value towards the target value by a fixed percentage of the remaining difference between the values. The current value will smoothly move towards the target, slowing down as it gets closer. Here is an example of a circle following the mouse using interpolation smoothing:

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

This is useful for smoothing camera movement, for allies following the player (ensuring they stay within a certain range), and for many other common game patterns.

備註

Despite using delta, the formula used above is framerate-dependent, because the weight parameter of lerp() represents a percentage of the remaining difference in values, not an absolute amount to change. In _physics_process(), this is usually fine because physics is expected to maintain a constant framerate, and therefore delta is expected to remain constant.

For a framerate-independent version of interpolation smoothing that can also be used in process(), use the following formula instead:

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)

Deriving this formula is beyond the scope of this page. For an explanation, see Improved Lerp Smoothing or watch Lerp smoothing is broken.