テラシュールブログ

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

【Unity】Animation C# Jobsで遊んでみる

Unite LAで盛り上がってますが、今回はソレは置いといてAnimation C# Jobsを試してみます。

Animation C# Jobs

Animation C# Jobsは言うならば 「アニメーションを独自実装するモノ」 です。
Playable APIや派生物(Animation Controller、Timeline、Simple Animator)が 「アニメーションの制御を定義するモノ」 なのに対して、アニメーションを実現するためのストリームに直接操作を行う機能です。

blogs.unity3d.com

そのため一工夫が必要ですがGameObjectを経由せず直接Skin Meshの行列への書込等も期待出来ます。

その他の用途としては、2ボーンIKやフルボディIKのようなコントロール、LookAtや揺れモノのようなエフェクト、マスク等があるみたいです。

www.youtube.com

www.youtube.com

作ってみたもの

f:id:tsubaki_t1:20181025233734j:plain

f:id:tsubaki_t1:20181025233531j:plain

ボーン構造を持つオブジェクトに対してEffectorの回転を流し込むだけのサンプルです。

実行前は単純に複数のボーン構造を持つようなオブジェクトですが、実行時に階層を平坦化して、かつ他のGameObjectから操作します。
コレはEffectorを使用していますが、実際にはNative ArrayでQuaternionを用意しておいてC# Job Systemでガガっと計算するなり、ファイルからストリームで書き込むなりするのが良いんじゃないかなと思います。

解説

f:id:tsubaki_t1:20181025234705j:plain

まずAnimation C# Jobsを実行するにはアバターが必ず必要です。基本アバターからストリームにアクセスしているので、コレが無い場合は InvalidOperationException: The TransformStreamHandle cannot be resolved. のエラーが出力されます。 もしモデルからインポートしていない場合、 Bind Generic Avatarを使用します 。実行後GameObjectの階層構造を変更した場合、アバターの再構築が必ず必要です。
なおバグか分かりませんがPrefabにBind Generic Avatarで作成したアバターは格納されてません。

f:id:tsubaki_t1:20181025234610j:plain

あとはAnimation C# Jobsで作成したジョブをPlayableに格納して実行します。

Animation C# Jobsで行うべき内容は3つ

  1. ジョブを定義し、ストリームにアクセスして色々とするコードを記述する
  2. アニメーションのStreamにアクセスする用のハンドルの取得
  3. Playable Graphにジョブを登録

まずはAnimation C# Jobsを定義します。

見るべき所は2点で、まずIAnimationJobを継承している点です。このインターフェースでAnimation Streamにアクセスします。

あとはハンドルを元にAnimaiton Streamからpositionやrotationを取得し、書き込みます。
もしAnimationClip等と連動したい場合、Playableの子としてアニメーションを再生しておきます。

f:id:tsubaki_t1:20181026000324j:plain

次は使用する側です。 Transformのハンドルを入手します。

animator.BindStreamTransformではAnimatorの子オブジェクトからハンドルを取得します。
正直これAvatarから取得すべきだと思うのですが、なぜか現状はTransformに必ずアクセスが必要です。多分Humanoidは回避出来ます。
このコードではtransform.Findで子オブジェクトを探索して取得しました。

なおTransformStreamHandleを取得したら用済みなので、AnimatorUtility.OptimizeTransformHierarchy(gameObject, null);でHierarchyをスッキリさせます。

あとはBindSceneTransformAvatar外のオブジェクトに対してのストリームを入手します。こちらは特にAvatarを用意したりする必要もなく、シーン内のオブジェクトにアクセス出来ます。
主にIKのエフェクター用です。

f:id:tsubaki_t1:20181025235253j:plain

あとはAnimation C# Jobsを登録します。
AnimationScriptPlayable.CreateでPlayableを作成し、作ったジョブを登録するだけです。
outputを云々するのが面倒くさいので AnimationPlayableUtilities.Play(animator, playable, graph);でサクッと動かしました。PlayableGraphを複数キャラクターで共有する良い子は真似しないでね。

f:id:tsubaki_t1:20181026000117j:plain

そこそこ配置して実行すると、こんな感じで実行されました。
それなりに並列化されています。

f:id:tsubaki_t1:20181026001205j:plain

コード

gist.github.com

感想

Playableを使用しないと使えない(=Animation Controllerをオーバーライドする)ので、ぶっちゃけ普通にGameObjectとLateUpdateでアクセスするのが楽そうな気がしますが、ストリームに直接云々出来るのは楽しいです。特にNativeArray経由でアニメーションデータを流し込んでやるとAnimationClip無しに色々できr…え?GameObjectベースでも出来るって? HAHAHA

関連

サンプルコード一覧です。

github.com

Playable APIとAnimation C# Jobsの比較があります

www.slideshare.net

聞いた話によるとKinematicaもAnimation C# Jobsで動いてるらしいです。

blogs.unity3d.com