今週の進み具合 #15 - アニメーションブレンディング

暑い日が続いてめっきり夏です。2 週間ぶりにゲーム開発の具合を振り返ってみます。

進み具合 (2014年6月24日 - 7月10日)

アニメーションブレンディングを実装しました。

(動画) 2つのアニメーションを入力とした線形補間 (Lerp) を使ったアニメーションブレンディング。

その他に実装したことは次の通りです:

  • 2D ゲーム向けのレンダリングパイプラインの作成
  • エンティティコンポーネントシステムの更新
  • ゲーム内エディタのリファクタリング

今回は、少し前の日記でも触れたアニメーションブレンディングについて、いつもの通りざっくり見ていきたいと思います。ソースコードはすべて GitHub で公開しているので、詳しい実装について知りたい方はそちらをご参照ください。

アニメーションブレンディング

複数のアニメーションを組み合わせて、新たなアニメーションを作成することを アニメーションブレンディング (Animation blending) と言います。今回実装したアニメーションブレンディングは、とてもシンプルなもので、2 つのアニメーション間を、重みをつけて線形補間して新たなアニメーションを実行時に計算しています。図 1 のアニメーションクリップ A と図 2 のアニメーションクリップ B から、最終的なポーズを生成しています。

(図 1) ビームライフルを構えながら走るアニメーションクリップ A
(図 1) ビームライフルを構えながら走るアニメーションクリップ A

(図 2) ビームライフルを下げつつ走るアニメーションクリップ B
(図 2) ビームライフルを下げつつ走るアニメーションクリップ B

この線形補間を用いるブレンディングをそのままLERP ブレンディングまたは重み付き平均を用いたブレンディングと言います。2 つ(またはそれ以上)のアニメーションを入力として、重みに沿って線形補間を行い、最終的なポーズを出力するという流れです。この計算を図に示したものが図 3 です。

(図 3) 2入力の 1 次元 LERP ブレンディングツリー
(図 3) 2入力の 1 次元 LERP ブレンディングツリー

図を見てお気づきの方もいると思いますが、LERP ブレンディングは木構造になっています。LERP のノードを演算子として見てみると、この木はある種の式木と言えます。このようなアニメーションブレンディングの式木をブレンディングツリーといい、昨今の 3D ゲーム開発では非常によく利用されています。ブレンディングツリーはコーディングを必要としないビジュアルなグラフとして扱いやすいため、GUI でアニメーションブレンディングを行えるノードエディタを提供しているミドルウェアも少なくありません。

線形補間(LERP)の他に、アニメーション結果を加算する加算ブレンディングや、スケルトンの任意の間接のみについて部分的にブレンディングを行う部分的なスケルトンブレンディングなどがアニメーションブレンディングの手法としてあります。これらも LERP のように、式木として表現することが可能です。 これらの演算子やツリーを組み合わせて、より複雑で、ダイナミックなアニメーションをゲーム内で作成し再生することができます。

ブレンディング係数(重み)

LERP ノードの重み w の値を変更することで、最終的な出力ポーズを変化させることが出来ます。図 4 は重み w をそれぞれ 0 から 100% まで 5 段階で変化させたときの最終的なポーズの例を示しています。

(図 4) 1 次元 LERP ブレンディングの重み w をそれぞれ 0, 20, 50, 80, 100% と変えたときの出力例
(図 4) 1 次元 LERP ブレンディングの重み w をそれぞれ 0, 20, 50, 80, 100% と変えたときの出力例

重みを変えることで、複雑なアニメーションを少ないアセットで動的に生成することができます。例えば、さわやかに走っているアニメーションと、へとへとになりながら走っているアニメーションの 2 つを作成すれば、その中間の表現を簡単に作ることが出来ます。「どちらかと言えば疲れているけど、まだまだ体力が残っている様子の走っているアニメーション」というような中途半端な表現も可能です。

エイミング

さらにこれを応用することで、様々なことができます。その 1 つがエイミング (Aiming), または単に エイム (Aim)と呼ばれるものです。これは、銃を使った FPS や TPS でよく使用されます。銃を構えたアニメーションを作成する際に、「正面方向を向いたもの」「右方向を向いたもの」「左方向を向いたもの」の 3 種類を作成します。これらを、実行時のキャラクターの注視方向に合わせて、アニメーションブレンディングします。これで 180 度どの方向にも対応したアニメーションを再生することが出来ます。 今回実装したアニメーションもなんちゃってエイミングをしています。LERP ノードの重みの値を変更することで、銃口の向き、銃の構え方が変化します。

アニメーションステートの遷移

キャラクターの状態(ステート)に合わせて、現在のアニメーションから次のアニメーションへとスムーズに遷移させることもゲームではよくあることでしょう。ブレンディングツリーに加えて、状態と遷移関数を対にしたステートマシンをアニメーションシステムとして提供しているゲームエンジンは多いです。ステートマシンも先ほどのブレンディングツリーのように図として表現しやすく、ビジュアルなノードエディタで編集できるものもあります。Unity の Mecanim がその代表的な例でしょう。ブレンディングツリー単体、またはステートマシンの遷移図も含めて、これらをアニメーショングラフ (Animation graph) と言うこともあります。

今週の予定

  • アニメーションステートの遷移
  • Lua スクリプティング

アニメーションブレンディングやアニメーションのステートマシンの記述を C++ で行うのは大変です。ソースコードに埋め込んだパラメータを変更するたびにコンパイルするのは、修行僧が険しい山奥で行う苦行そのものでしょう…(汗)
ノードベースのグラフィカルなエディタを作る余力もないため、Lua を使ってスクリプトという形でアニメーショングラフを記述しようと思います。Lua でスクリプティングが可能になれば、そのままゲームコーディングもできるようになります。コンパイル待ちはできるだけ回避したいところです。

(次回、"今週の進み具合 #16" の更新が遅れないようにします…。お楽しみに。)

参考文献

  • 『ゲームエンジンアーキテクチャ』 ジェイソン・グレゴリー著、大貫宏美、田中幸訳、今給黎隆、桐山忍、鴨島潤、湊和久監修、ソフトバンククリエイティブ。第11章「アニメーションシステム」参照。

Leave a Reply