読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】AnimationControllerがプロジェクトを散らかさない設計についての模索とサンプル

f:id:tsubaki_t1:20160516005140j:plain

Animatorの運用方法について、5つのアプローチを試しに試作してみました。

サンプルプロジェクト

作成したサンプルプロジェクトは、下のリンクから取得出来ます。作成にはUnity 5.4 b17を使用しています。多分5.3系でも動きますが、未検証です。

github.com

プロジェクトにはStyle{任意の番号}というフォルダが含まれており、これが各アプローチと一致します。

このプロジェクトでは、可能な限り、各アプローチは各フォルダ内で完結するようにしています。+3Dは指定のスタイルの3D版です。

f:id:tsubaki_t1:20160516005703j:plain

Style1:各ステートマシンにて制御

Style1は各ステートマシンに各々のアニメーション制御を設定しているパターンです。マニュアルやチュートリアルで紹介している方法でもあります。

各々のアニメーションステートがアニメーション制御を持つため、各々の独立したアニメーション制御を作成する事が出来ます。反面、特定のパターンからアニメーションを量産しようとすると、非常に手間のかかるパターンです。

アニメーションの切替はAnimator.CrossfadeやAnimatorに対してSetParameter系を使用します。

f:id:tsubaki_t1:20160516010432g:plain

このアプローチはメッシュとアニメーションが分かれている3Dで、1キャラクター毎に独自の設定がある場合は使い勝手が良いです。例えば格闘ゲームや、膨大かつユニークなスキルを持つ現世代の3DRPGキャラクターのような。
反面2Dスプライトアニメーションや特定のパターンからキャラクターを量産するタイプでは、非常に冗長な結果になりそうです。またステートマシン設計を上手く出来ない人には非常に使いにくいシステムです。

なおTransitionの数がものすごい数になると、それ自体が負荷になりますし修正も複雑になるので、至る所へTransitionしてるようなステートでは出来るだけ避けたい所です。

Style2:ステートマシンのアニメーションを上書き

Style2では、単一のステートマシンを作成し、ステートマシンのクリップを上書きするパターンです。
Style1と比較してステートマシンが1つしかない為に更新が容易ですが、逆にキャラクター毎のステート微調整がやりにくくなります。

またAnimationClip名ではなくStateでアニメーションの切替制御が出来るので、汎用的なアニメーション制御をする場合には楽に使えます。

f:id:tsubaki_t1:20160516011255g:plain

このアプローチは、同様のパターンを持つ幾つかのキャラクター制御を行う場合に便利です。例えば「移動」と「停止」あと「攻撃」のようなパターンを持つキャラクターを表現する場合には使い勝手が良いです。

Style3:AnimatorOverrideControllerを「シーンにシリアライズ

Style3は、Style2の応用でAnimatorOverrideControllerを実行時に作成・上書きするアプローチです。ただし、OverrideControllerをプロジェクトではなくシーンに保存しています。
つまり、プロジェクトにはAnimationController1つとClip達だけで、ファイル毎にAnimationControllerやAnimatorOverrideControllerを作成しません

プロジェクトに保存しないため、1アニメーションしか持たないユニークなオブジェクトがプロジェクトに大量のファイルを作るのを防げそうです。

f:id:tsubaki_t1:20160516012402j:plain

作成したAnimationControllerは、シーン内で設定したアニメーションで確認します。少しエディタを拡張すれば、もっと手軽にアニメーション設定ができる気がします。

f:id:tsubaki_t1:20160516012558j:plain

シーンに保存しているため、プロジェクトにはシーンとオリジナルとなるAnimationController、それとコレを実現するためのエディタ拡張のみです。

f:id:tsubaki_t1:20160516012430j:plain

このアプローチの問題は、プレハブの扱いです。
このアプローチにて作成したオブジェクトをプレハブとしてシリアライズした場合、、プレハブのAnimationControllerはMissingになります

 

このサンプルでの設定方法

  1. オブジェクトもしくはプレハブを選択する
  2. GameObject>AddOverrideAnimationControllerを選択
  3. アニメーションコントローラーに使いたいアニメーションコントローラーを選択
  4. Createを押す
  5. OverrideAnimationControllerがAnimatorに設定されるので、クリップを登録

f:id:tsubaki_t1:20160516014436j:plain

なお、初期値はエディタ拡張のスクリプトに直接設定しています。

f:id:tsubaki_t1:20160516014731j:plain

Style 4:AnimatorOverrideControllerを「動的に生成・差替」

Style 4は3の発展形で、AnimatorOverrideControllerをスクリプトにて動的に生成しAnimatorに設定し、アニメーション切替時にはClipの差替を行います。プロジェクトの中身はスッキリしています。

f:id:tsubaki_t1:20160516085358j:plain


このアプローチはステートマシンによるアニメーション制御は行っていません。そのため、AnimationClipをいくらでも動的に増減・切替する事が可能です。

f:id:tsubaki_t1:20160516015538j:plain

このアプローチでは2つ問題があります。

問題はClip更新時にAnimatorが初期化される事です。これは単純にアニメーション切替を行うのと比較してCPU負荷がかかるのと、初期化時に現在の状態が失われてしまいブレンドが行えなくなる問題が発生する点です。

特にブレンドが効かなくなるのは…正直いってそれほど重要では無い気がしますが、対策が無かったので何とも。

単純な2Dゲームや単一のアニメーションをループするタイプならば、これでも問題は無いのですが、それ以外となると少し厄介です。

Style5:AnimatorOverrideControllerを「動的に生成・制御」

Style5では、幾つかのClipを持つAnimatorを保持しておき、実行時にAnimationOverrideControllerでアニメーションをセット・Animator.Play等で切り替えるアプローチです。

実行時にAnimationClipを登録していく、Animationにかなり近いアプローチになります。(登録の更新時にAnimatorが初期化されます。この辺りもAnimationっぽい)

一応このサンプルでは、設定するAnimationClipの数とステートの数が一致するようになっています。

f:id:tsubaki_t1:20160516020739j:plain

Style5ではStyle4で問題となったClip切替時の負荷やブレンドの問題が解消されていますが、AnimationClipを登録したAnimationControllerを事前に登録する必要があります。

沢山のアニメーションを登録したい場合は、AnimationController作成部分をエディタ拡張でガガっと作った方が良いかもしれません。

割と気持ちの悪い使い方ですが、使ってて一番使い勝手が良さそうな気がしています。プロジェクトの中身もスッキリです。

f:id:tsubaki_t1:20160516085441j:plain

Style6(追記):Playable API

tsubakit1.hateblo.jp

感想

Style3~5はエンジンに踊らされている感じがありますが、Prefabベース開発やアクティブスイッチ、1Asset1AssetBundle等が事例があるので今更です。

Unityの機能を素直に使った場合のStyle1ですが、コンテンツ量産型ゲームでは相性が悪いので、もう少し色々と模索したい所です。

 

個人的には、基本的にはStyle2で行い、特殊な状況でStyle4かStyle5を利用する感じが良さそうなきがしますが、どうでしょう。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp