ひとことで
現在の値を目標へ「残りの距離の一定割合ずつ」近づける追従を、経過時間 から係数を計算することでフレームレートに依存しない形にしたものです。追従カメラ、照準、UI の値の変化など、「滑らかに追いかける」処理の最も基本的な道具です。
ゲームでの使いどころ
- 追従カメラ:プレイヤーの位置をカメラがわずかに遅れて追う。
- 照準・ロックオン:レティクルが敵へ吸い付くように移動する。
- 数値の表示:HP バーの減少、スコアのカウントアップ、音量のフェード。
- 入力の平滑化:スティックの入力やマウス移動を滑らかにしてブレを抑える。
しくみ
よく見る書き方は次のようなものです。
これは「1 フレームで残りの距離が 0.9 倍になる」という意味です。60fps なら 1 秒で 倍、30fps なら 倍になり、フレームレートによって追従の速さが変わってしまいます。高リフレッシュレートのモニターでだけカメラが速い、というバグの典型的な原因です。
時間に対して正しく減衰させるには、「1 秒あたりの減衰率」を決め、経過時間に応じて累乗します。連続時間で書くと
なので、lerp の係数を次のようにすればよいのです。
は半減期(残りの距離が半分になるまでの時間)です。「0.25 秒で半分」のように、フレームレートと無関係な直感的な単位で調整できます。
実装のポイント
- エンジンの関数:Unity の
Vector3.SmoothDampや Unreal のFMath::FInterpToは同じ目的の関数です(SmoothDamp は速度も持つ臨界減衰ばね)。 - 回転:四元数の場合は
slerp(current, target, k)に同じ係数を渡します。 - 角度のラップ:角度をそのまま減衰させると 359° → 1° で逆回りします。差を に正規化してから計算します。
つまずきやすい点
- いつまでも到達しない:指数減衰は理論上目標に一致しません。一定の距離より近づいたら目標値に丸めるか、完了判定に閾値を使います。
- 動く目標には遅れが残る:一定速度で動く目標に対しては、 の距離だけ常に遅れます。遅れを減らしたいなら先読み追従やばねを使います。
- 速度が不連続:目標が急に変わると、追従側の速度も瞬時に最大になります。動き出しを滑らかにしたいなら、速度を状態として持つ臨界減衰ばねが向きます。
デモで試すこと
- 赤(20fps)とピンク(120fps)の球は同じ
lerp(x, 目標, 定数)ですが、ピンクのほうが明らかに速く追いつきます。左下の「残り距離」を比べてください。 - 水色と青の球は指数減衰です。20fps と 120fps で更新しているのに、ぴったり重なって見えます(差は 0.000 m 付近)。
- 「半減期」を変えると、フレームレートに関係なく追従のきびきび感だけが変わります。床をクリックして目標を置き、確かめてみてください。