takeyohのおぼえがき

気になったこと、試したことの記録です。

アニメーションを速度やRPMに合わせてシームレスに動かす。

例えば、自転車のmodでもそうでしたが、タイヤ以外のアニメーション、ペダルや足の動きは、スピードやRPMに合わせて再生速度を変えることができなかったため、速度やRPMを4段階くらいに分けて、各レンジごとにloop再生速度を変えて表現していました。
これでも良いと言えばよいのですが、やはりスピードやRPMに合わせてシームレスにアニメーションしてほしいですよね。
今回そのやり方を教えていただき、いろいろテストした結果、ようやく実装できたので、その覚書です。

まず、今回の方法はext_config.iniのANIMATIONで設定できるものであれば、car mod側でもドライバ側でもどちらにも対応できます。
ただし、ドライバのアニメーション制御については、animationsフォルダにsteer.ksanimが存在する場合うまく制御できません。
このため、もしステアリングやシフトチェンジ以外のアニメーションをドライバにさせたい場合(そんな機会あまりないかもしれませんが)、
steer.ksanimを別名にして、下記の制御に一緒に組み込む必要があります。

まず、extensionフォルダのext_config.iniにlua scriptを読み込む設定を追加します。

[SCRIPT_...]
SCRIPT="leg.lua"
SKIP_FRAMES = 0
ACTIVE_FOR_NEAREST=20
ACTIVE_FOR_UNFOCUSED=1

ACTIVE_FOR_UNFOCUSED=1を設定すると、リプレイ時に車から遠ざかっても、アニメーションが継続されます。
これを設定しないと、20m離れたところでスクリプトは動かなくなります。
車内のアニメーションとかならそれの方が処理も軽くて良いのですが、今回足のアニメーションは外からもろ見えるので距離が離れてもアニメーションが動くように設定しています。
ACTIVE_FOR_NEAREST=20は、AI車として使った場合、自車から見て20台以内に入るとスクリプトが動くというものです。
AI車として使っても動くようにするためには、この設定が必要ですね。

スクリプト名は何でもよいです。今回は椅子modのドライバの足のアニメーションを例にするので、leg.luaという名前になってます。
で、足のアニメーションはanimationsフォルダにleg.ksanimとして保存しています。
また、椅子modはハンドリングが無いので、steer.ksanimは削除しています。

つづいて、extensionフォルダにleg.luaを作成して以下を追記します。

local legAnimFile = "../animations/leg.ksanim"
local progress = 0
local driverRoot = ac.findNodes('DRIVER:DRIVER')

function script.update(dt)
    progress = (progress + dt * ac.getCar().speedKmh/10) % 1
        driverRoot:setAnimation(legAnimFile,progress,false)
end

1行目がアニメーションファイルの場所
2行目はアニメーションの進捗率(0~1)。初期値として0を設定。
3行目がアニメーションを反映させるノード(エンプティ)を指定。ドライバの場合はDRIVER:DRIVERになります。
(car modの場合は、アニメーションを設定しているエンプティ名で指定します。)
4行目以降がアニメーションの制御部分。
5行目がアニメーションの進捗率の計算です。この計算にspeedKmhやRPMを組み込むことで、それらの値に連動した制御が可能になります。
ただし、アニメーションは何秒間という設定ではなく、一つの周期が0~1で制御されています。
%1(1で割った余り)を代入することで、0~1をループするようになります。
6行目がアニメーションの設定。アニメーションのループスピードを変更するのではなく、アニメーションの進み度合いをprogressで都度設定して制御しています。
これは目から鱗な方法です。なるほどね~。

今回の例では、ドライバの足のアニメーションとなっていますが、同じことを例えばキャタピラとか、バイクのチェーンとか、car modのパーツに対しても適用することが可能ですね。
ただ、メッチャ大変だと思いますけど。(笑)

/* -----codeの行番号----- */