はじめに
こんにちは、サイバーエージェントゲームエンターテイメント事業部
SGEコアクリエイティブ本部所属の3Dアーティスト 畠 と申します。
今回はゲーム開発における3Dアニメーションの作り方
「接地感のある歩き」についてお話しさせていただきます。

3Dゲームにおけるキャラクターの移動は、ゲームバランスや企画内容によって移動スピードが指定されます。
アニメーターはキャラクターの性格を踏まえつつ
その指定されたスピードで移動するアニメーションを作成しなくてはなりません。
このブログは移動スピードが設定された条件で
「足を滑らせない、接地感のあるアニメーション」の作り方に重点をおいて説明します。
◯使用するモデル
リアル等身のモデルを使い説明します。
アニメーション作成はMAYAに標準搭載されているHumanIKのコントローラーを使用していきます。

今回の作成では腕はFK、足の移動はIKでアニメーションを付けていきます。
途中でFKとIKを切り替えることは説明が複雑になるので行いません。
リグのトップノード(以降、Rootノードと呼称します)を動かすと全身が移動する構造です。

◯前提条件
歩きのアニメーション作成の前提条件は以下になります。
- 歩く速さ:秒速180cm
- フレームレート:30fps
※この歩く速さは実際の人間が歩くスピードよりだいぶ速いものとなります。
必ずというわけではないですが、プレイヤーがキャラを操作するときのレスポンス的な観点で速めになることが多いです。
Mayaプリファレンスの設定


◯歩きのループアニメーションを作成
「歩き」のアニメーションデータを作成する際はプログラム上で制御しやすいように
1サイクルのループアニメーションにすることが基本となります。
まず、その場で歩きのループをアニメーション作ってみます。
何フレームで1サイクルさせるかに決まりはないですが
わかりやすい数値で0~30フレームでアニメーションレンジを設定しました。
30fpsなのでちょうど1秒のアニメーションになります。
その場でのループアニメーションをこんな感じで作成しました。

◯Rootノードに移動値を入れる
Rootノードに前方向(+Z方向)へ移動させるリニアのアニメーションカーブを設定します。
指定速度は秒速180cmなので1秒のとき(30フレーム)に値180のカーブです。
このアニメーションのキー接線は「リニア接線」にしてください。

アニメーションを再生してみます。

足が少し滑っているのがわかると思います。
ここから足が滑らない様に調整をしていくのですが、まずは下準備をします。
◯足のIKのアニメーションカーブをワールドスペースのアニメーションカーブに変換する
ロケータを3つ作成します。

わかりやすい名前をそれぞれつけていきます。 今回は、以下のように名前を付けました。
- World_Move
- World_LeftLeg
- World_RightLeg

World_LeftLeg、World_RightLegがWorld_Moveの子どもになる様にペアレント化します。

何も選択していない状態から
左足のIKノード > World_LeftLegの順番で選択し ポイントコンストレイントをかけます。
同様に、何も選択していない状態から
右足のIKノード > World_RightLegの順番で選択し ポイントコンストレイントをかけます。
「編集」>「キー」>「シミュレーションのベイク処理」オプション(四角いアイコン)を選択。
「シミュレーションのベイク処理オプション」ウィンドウが開きます。
「チャネル」項目の チャネルボックスから を選択します。
設定の保存をしてこの「シミュレーションのベイク処理」オプションウィンドウを閉じます。

チャネルボックスで移動XYZを選択

World_LeftLeg、World_RightLegの2つを選択して
「編集」>「キー」>「シミュレーションのベイク処理」を実行します。
-ベイク処理の結果-

World_LeftLeg、World_RightLegのコンストレイントノードを削除します。

手順の4番とは逆にコンストレイントをかけます。
World_LeftLegを選択 > 左足のIKノードを選択し ポイントコンストレイントを実行します。
World_RightLegを選択 > 右足のIKノードを選択し ポイントコンストレイントを実行します。
これで World_LeftLegが左足、World_RightLegが右足を制御する状態になりました。
再度アニメーションを再生します。
先ほどと変わらないアニメーションをします。
アニメーションは変わっていませんが両足とも、ワールドスペースで動いてる状態に変換されたということになります。
◯足のIKアニメーションをワールドスペースで調整する
World_LeftLegを選択して、グラフエディタでトランスレーションのアニメーションカーブを見てみます。

TransZの値が足の前後の移動を示しているのですが
このアニメーションカーブでは同じ値で止まっているフレームがありません。
つまり、足が接地して止まっている時間が無いことを示しています。
ここから、足のアニメーションをワールドスペースで調整していきます。
このアニメーションの左足が地面に着いた 8フレーム から
地面を蹴り始める 15フレームまでは左足は接地させるようにしたいので、キーフレームを調整します。

Z軸のアニメーションキー、8フレームから15フレームまでを同じ値にします。

アニメーションを再生してみます。

左足だけ注目してください
アニメーションキーを同じ値にした部分の足が滑らず接地している状態になりました。
ただ、15フレーム以降では
足が浮いてる、ポーズが跳んでいる、足が伸び切っているなどおかしなところが出てきてしまいました。
ここから、足の運びが自然に見えるように、Z軸だけでなく
移動のX、Y軸、足首の回転の値も自然に見えるように調整していきます。
World_LeftLeg Z軸の調整後のカーブ

調整後のアニメーション

納得の行く左足のアニメーションができたら、右足の調整です。
World_RightLegのアニメーションカーブのキーを0フレームだけ残して削除します。

同じ様に足首の回転を制御しているノードのカーブのキーを0フレームだけ残して削除します。

World_LeftLegのアニメーションカーブをコピーしてWorld_RightLegにペーストします。

同様に左足首の回転制御しているノードのアニメーションカーブを 右足首の回転を制御しているノードにペーストします。

このままだと下の動画のように左足と右足が重なった動きになるのでアニメーションカーブを編集します。

交互に足を出すようにするため、ペーストした右側の足の移動、回転のアニメーションカーブを
総フレーム数の半分のフレーム数 マイナス方向に移動します。
このシーンだと総フレームが30フレームなので半分の15フレーム、マイナス方向に移動します。

移動したカーブをコピーして15Fにペーストします。

X軸とY軸はきれいにカーブがつながりますがZ軸は移動しているため繋がりません。
Z軸のアニメーションカーブ、最終フレームの値の半分の値を計算し
Z軸のアニメーションカーブの前半部分は(-)マイナス方向に後半部分は(+)プラス方向にその値ぶん移動させます。
このシーンだと最終の30フレーム時の値は180cmなので半分の値は90cmになります。
Z軸のアニメーションカーブの前半は -90、後半は +90 アニメーションカーブを移動します。

Z軸もきれいに繋がりました。

右足首の回転アニメーションカーブも同様に総フレーム数の半分のフレーム数 マイナス方向に移動します。

移動したカーブをコピーして15Fにペーストします、回転のカーブはきれいに繋がります。

アニメーションを確認します。

足が交互に出るようになりましたが、まだおかしな部分があります。
このリグでは下記のアニメーションカーブの調整が必要になります。
右足が左側に移動してしまっているのでWorld_RightLegの移動X軸のアニメーションカーブを、値を0を起点に反転します。

次に右足先が少し左側を向いているので回転X軸、Y軸のアニメーションカーブを、値を0を起点に反転します。
(右足首の回転はWorld_RightLegではなくリグの方です。)

出来栄えに納得がいかなければ、再度左側の足を調整して右側にコピーする作業を繰り返し
納得がいくアニメーションになるまでブラッシュアップするのですが一旦はこれでアニメーションが完成したものとします。

◯ゲームでのRootノードの移動値の書き出しについて
ここまでの作業で歩きのアニメーションはRootノードに移動値の入ったアニメーションになっていますが
ゲームの仕様によって、Rootノードの値をどのような状態にして書き出すかが変わります。
主に下記のどちらかで出力するのが多いかと思います。
・Rootノードに移動値(アニメーションカーブ)が入ったままで書き出しする場合
・Rootノードは原点のまま(移動 X:0,移動 Y:0,移動 Z:0)で動かさず
その場でループしている状態にして書き出しする場合
Rootに移動値が入ったままで良い場合は現状のまま書き出しすれば良いのですが
その場でのループアニメーションに変更して書き出す場合は、また一工程作業が必要になります。
◯その場でループするアニメーションに変換する
アニメーションスライダを 0F にします。
World_Moveの移動Zに値 0 でキーフレームを設定します。
次に最終フレーム(30フレーム)に値 -180 でキーフレームを設定します。
このアニメーションのキー接線は「リニア接線」にしてください。
Rootの移動Zのカーブを打ち消すアニメーションカーブをWorld_Moveに設定したことになります。


Rootの移動Zのカーブ選択して グラフエディタのメニュー > 「カーブ」 > 「チェンネルのミュート」
カーブをミュート(mute)します。


その場でループするアニメーションになりました。

Root移動値なしの場合は、この状態でFBXファイルなどゲームエンジンで読み込めるファイルへ書き出しとなります。
最後に
ゲーム制作において、移動系のアニメーションを作成する場合は
一度作って終わりではなく、ゲーム上で実際に動かして何度も確認します。
・プレイヤーの操作に対して気持ちよく動いているか?
・ゲームのカメラで見ておかしな動きをしていないか?
・別アニメーションから歩きに遷移、歩きから別アニメーションに遷移するときの滑らかさ
などを何度も何度も確かめて調整していきまます。
ときには待機ポーズの変更や移動速度が変更されることもあるので
移動アニメーションは開発の最後まで手をいれることがあるアニメーションになります。
上記の作成方法が、より良いデータ作成の手助けになれば幸いです。
*1:移動したいアニメーションカーブを全て選択して
グラフエディタのツールバー、詳細(Stats)フィールドのキータイムのところに
【 -=15 】と入力してエンターキーを押すとアニメーションカーブがマイナス方向に15移動します。
【 +=15 】と入力すればプラス方向に15移動します。

*2:移動したいアニメーションカーブを全て選択して
グラフエディタのツールバー、詳細(Stats)フィールドの値のところに
【 -=90 】と入力してエンターキーを押すとアニメーションカーブがマイナス方向に90移動します。
【 +=90 】と入力すればプラス方向に90移動します。

*3:反転したいアニメーションカーブを選択して
グラフエディタのツールバー、詳細(Stats)フィールドの値のところに
【 *=-1 】と入力してエンターキーを押すとアニメーションカーブが値 0 を起点に+-反転します。

*4:もちろん、リグの足のIKにキーをベイクして
World_LeftLeg、World_RightLegのコンストレインを削除してしまっても良いのですが
それだと修正する際に、都度フルベイクしたキーで編集をしないといけなくなります。
World_Moveと、Rootのカーブを切り替える方法だと何度もベイクをしないで
アニメーションを修正できるメリットがあります。
再度、移動させながら編集する際はアニメーションスライダを 0F にしてから
World_Moveの移動Zのアニメーションカーブをミュートして
Rootのアニメーションカーブのミュートを解除します。