Lerp(線形補間)をプログラムで実装する方法

安原祐二氏(以下、安原):パート6ということで、Easing解析の話をしていきましょう。これはまず動画から見ていきましょうか。

すごくありがちな話ですが、UIとかをこうやってヒョヒョヒョヒョヒョッと出すのがよくあるじゃないですか。実装も簡単なのでよく使うのですが、今日はこれの性質を徹底的に考えていきましょう。

練習問題です。代表的な実装例はこうです。Lerpというのがあります。pとオレンジ色で書いてあるものが両方に含まれているのがポイントです。これはプログラムなので、1つ前の値が次の値に使われるということになります。要するに漸化式ですね。

Lerpは、Vector2版やVector3版があるのですが、これはx軸y軸それぞれやるだけの話なので、なんてことはありません。

復習すると、LerpはLinear Interpolationのことです。線形補間と訳されますが、aというポイントとbというポイントがあったら、そこを点線で結んで、なぞっていくものを式で作りたいわけです。

(スライドを示して)今ここに書いていますが、(1−t)にaを掛けて、bにtを掛ける。覚えにくいと思いますが、これも覚えておいたほうがいいです。覚えるとけっこう便利です。

覚え方ですが、tに0を入れた時にaと一致するようにする、tに1を入れた時にbと一致するようにする、と考えるとそんなに難しくはないかなと思います。

このとおりにプログラムでは実装します。自分で実装することはないと思いますが、こういうふうになっています。さっきの式をそのまま書いているだけです。

一般項を求める方法

それを呼び出すほうは毎フレーム呼ぶよと。ここから数学の話にいくのですが、つまり、この毎フレーム呼んでるほうを漸化式で置き換えると、こういう感じになるでしょうと。例えば0.1というのがあったら、こうなっている。

この一般項を求めることがまず最初の目標になるわけです。前の値を使わずにいきなり(答えを)出せるか。つまり数学的に言うと、問題はこうなります。Tとαにしましょう。0.1の代わりにαにして、目標をTとしましょう。これを一般項を求めよという問題を解けばいいわけですね。

漸化式なので、P0=0と初項は必要です。ちょっとがんばってやっていくのですが、ここはけっこう受験テクニックみたいな話になります。退屈かもしれませんが、順番に見ていきましょう。

この2つ目のテクニックが最大の山場です。これはもう完全に数学のテクニックです。Pn+1およびPnの代わりにsというのを置いて、そういうsがあるでしょと仮定しちゃうわけです。

なんでこういうことをするかというと、こういう式をでっち上げて、上から下を引くんですね。この2式を引き算すると、Tαの部分が消滅します。つまり、このTαを消滅させたかったわけで、そのためのsです。

Tαが見事消滅したので、Pn−sみたいなやつをqnと置くと(qn=Pn−s)、非常に単純な等比数列になるのがわかるでしょうか。公比1-αの等比数列が(スライドを示して)ここに現れるので、これで一般式は出てきます。

あとはqやsを元に戻していきます。qを戻して、sはこの上から2番目の式を解けばTと一致することがわかるので、sの代わりにTを置いて、はい、これが答えになります。見事に一般項が出ました。

というわけで、一般項が出たら何がうれしいかというと、グラフを書けるようになります。こんな感じです。60フレーム後に、だいたいこの位置に行っていることがわかります。αに0.1を入れた場合は、こんな感じになります。

Lerpの係数を一般化する方法

「一般項を求めてめでたしめでたし」ではなくて、こうやってターゲットが動的に動いても付いていくというのをプログラム中に使うのがけっこう便利だったりします。Lerpの本当にうれしい真髄というのはこれです。

60fps版で0.1だったら30fps版でここに何を入れたらいいのかというのがわかると便利です。これで一般化できたということになります。漸化式のままでこれができるかという話です。

これはもうゴリゴリとやっていくという話ですが、まず60fpsの時の係数をαとしておくと、このnの1秒後というのは60になるんですね。30fpsの時はβとしましょう。という計算をしていきます。

つまり60乗と30乗でαとβを導き出せばいいので、60と30の代わりに、mとかnとかを置いてしまえばより一般的な式ができてβが出せます。

これの何がうれしいかというと、60fps版はこうでした。じゃあ30fps版は? というのがもう出るわけです。先ほどの式でありましたが、べき乗、つまりPowというものを使います。Powerを使うとβという係数が出ます。30fps版の係数が出ます。実際は60割る30で2なので、2乗でも出るんですけれども。なぜPowerを使っているかというと、これですね。汎用的にどのフレームレートでも同じ動きをさせようと思ったら、30で割る代わりにdeltaTimeを掛けると、60fpsよりも高いフレームレートでも、同じ動きが作れるようになります。

もちろん30fpsの赤い玉のほうがガクガクしていますが、動きは一致しているのがわかるでしょうか。

フレームレートの異なる環境に対応できるようになる

こういうのが役に立つか立たないかという話になるんですが、例えばよくある話で言うと、最新のiPadは120fpsに対応しています。あるアプリを作って動きを作って、このデバイスだけ120フレームで動いてると、補間がそこだけ早くなっちゃうじゃないですか。でも、同じ動きで滑らかにしたいのが120fpsのうれしさなので、今の式を知っているとそういうところにも対応できます。

または、Windowsでゲームを作っていると、モニターのリフレッシュレートはけっこうまちまちですよね。最新だと144hzみたいなものもあるので、ここで一般化できるのは非常に大きな武器になります。

というわけでパート6、ちょっと難しい話になったかもしれませんが、難しかったのは数学の部分ですよね。でもあれはググると解き方がけっこう出てくるので、解けるんだということをわかっておくことが大事ですね。解く羽目になったら調べてがんばれば解けます。

これもブログ書いたので、ぜひあとで見てください。ここはわりと役に立つ情報が書いてあると思います。パート6は以上です。