Unite LAで盛り上がってますが、今回はソレは置いといてAnimation C# Jobsを試してみます。
Animation C# Jobs
Animation C# Jobsは言うならば 「アニメーションを独自実装するモノ」 です。
Playable APIや派生物(Animation Controller、Timeline、Simple Animator)が 「アニメーションの制御を定義するモノ」 なのに対して、アニメーションを実現するためのストリームに直接操作を行う機能です。
そのため一工夫が必要ですがGameObjectを経由せず直接Skin Meshの行列への書込等も期待出来ます。
その他の用途としては、2ボーンIKやフルボディIKのようなコントロール、LookAtや揺れモノのようなエフェクト、マスク等があるみたいです。
作ってみたもの
ボーン構造を持つオブジェクトに対してEffectorの回転を流し込むだけのサンプルです。
実行前は単純に複数のボーン構造を持つようなオブジェクトですが、実行時に階層を平坦化して、かつ他のGameObjectから操作します。
コレはEffectorを使用していますが、実際にはNative ArrayでQuaternionを用意しておいてC# Job Systemでガガっと計算するなり、ファイルからストリームで書き込むなりするのが良いんじゃないかなと思います。
解説
まずAnimation C# Jobsを実行するにはアバターが必ず必要です。基本アバターからストリームにアクセスしているので、コレが無い場合は InvalidOperationException: The TransformStreamHandle cannot be resolved. のエラーが出力されます。
もしモデルからインポートしていない場合、 Bind Generic Avatarを使用します 。実行後GameObjectの階層構造を変更した場合、アバターの再構築が必ず必要です。
なおバグか分かりませんがPrefabにBind Generic Avatarで作成したアバターは格納されてません。
あとはAnimation C# Jobsで作成したジョブをPlayableに格納して実行します。
Animation C# Jobsで行うべき内容は3つ
- ジョブを定義し、ストリームにアクセスして色々とするコードを記述する
- アニメーションのStreamにアクセスする用のハンドルの取得
- Playable Graphにジョブを登録
まずはAnimation C# Jobsを定義します。
見るべき所は2点で、まずIAnimationJob
を継承している点です。このインターフェースでAnimation Streamにアクセスします。
あとはハンドルを元にAnimaiton Streamからpositionやrotationを取得し、書き込みます。
もしAnimationClip等と連動したい場合、Playableの子としてアニメーションを再生しておきます。
次は使用する側です。 Transformのハンドルを入手します。
animator.BindStreamTransform
ではAnimatorの子オブジェクトからハンドルを取得します。
正直これAvatarから取得すべきだと思うのですが、なぜか現状はTransformに必ずアクセスが必要です。多分Humanoidは回避出来ます。
このコードではtransform.Find
で子オブジェクトを探索して取得しました。
なおTransformStreamHandleを取得したら用済みなので、AnimatorUtility.OptimizeTransformHierarchy(gameObject, null);
でHierarchyをスッキリさせます。
あとはBindSceneTransform
でAvatar外のオブジェクトに対してのストリームを入手します。こちらは特にAvatarを用意したりする必要もなく、シーン内のオブジェクトにアクセス出来ます。
主にIKのエフェクター用です。
あとはAnimation C# Jobsを登録します。
AnimationScriptPlayable.Create
でPlayableを作成し、作ったジョブを登録するだけです。
outputを云々するのが面倒くさいので AnimationPlayableUtilities.Play(animator, playable, graph);
でサクッと動かしました。PlayableGraphを複数キャラクターで共有する良い子は真似しないでね。
そこそこ配置して実行すると、こんな感じで実行されました。
それなりに並列化されています。
コード
感想
Playableを使用しないと使えない(=Animation Controllerをオーバーライドする)ので、ぶっちゃけ普通にGameObjectとLateUpdateでアクセスするのが楽そうな気がしますが、ストリームに直接云々出来るのは楽しいです。特にNativeArray経由でアニメーションデータを流し込んでやるとAnimationClip無しに色々できr…え?GameObjectベースでも出来るって? HAHAHA
関連
サンプルコード一覧です。
Playable APIとAnimation C# Jobsの比較があります
www.slideshare.net
聞いた話によるとKinematicaもAnimation C# Jobsで動いてるらしいです。