本当に良い機能なのか?

山村達彦氏(以下、山村):ここまでがんばって紹介してきましたが、実際問題として「こんな機能いらない!」というケースがけっこう多いです。

Animator Controllerを使うより、どちらかと言えばスクリプトで制御したほうが楽に作れるので、AnimationClipを大量に登録して、スクリプトで上書きするのはよくあることです。

実際、どんな機能が必要なのかというと、キャラクターを移動する機能はいりませんし、再生するべきアニメーションを自分で選択する機能も必要ありません。「スクリプトでやったほうが作りやすい」という人が多いです。私もそのほうが作りやすいです。

場合によってはGameObjectを経由せずにマトリクスに直接書き込む機能と、AnimationClipを共通化するリターゲットの機能の2つだけです。

Simple Animation

ということで、いろいろ言われ続けた結果、最近追加されたのがSimple Animationです。

私はすごく好きです。かつてはバグもありましたが、だいぶ直りました。

基本的なコンセプトは、AnimationClipコンポーネントの使い勝手はそのままに……要するに「Animator Controllerいらんよ」という(笑)、そんな機能です。これはUnityのなかに組み込まれているわけではなく、GitHubで公開されています。

先ほども紹介したとおり、基本的な機能は非常にシンプルで、AnimationClipを突っ込んだらアニメにしてくれる機能です。ただ、動作自体はAnimationではなく、Animatorで動いています。アニメーションの部分に関しては、Animatorに全部集約されています。

これをどのようにして実現しているのかというと、Playable APIというものが使われています。これは5.5あたりで追加され、2017でちゃんと組み込まれた機能ですね。

考え方としては、ツリー構造を作って、その評価でどのアニメーションを実行するのかを判断する機能です。そのツリー構造は自分で定義することができます。その時にウェイトを設定して、そのウェイトがどのくらい高いのかで、どのアニメーションを再生するのかを選択しています。

これを使ってどんなことが実現できるのかというと、例えばAnimator Controllerの階層化ですね。特定のステートに入った時に、Animator Controllerを作るといったことや、複数のAnimator Controller同士をブレンドしたり。

もっとシンプルなアニメーションを作ることもできます。Simple Animationはレイヤー機能を持っているんですが、こういったものも全部移してしまって、普通にAnimationClipを再生するだけという機能を作る場合にも便利です。もしくは、独自のアニメーション……もっと別のアニメーションを管理する機能を作らせることもできます。基本的にPlayable APIは、Animationの低レイヤーのAPIとして活用されています。

Animationを再生するところではなく、Animationを制御するところです。Simple Animationなどでは、単純にアニメーションを再生するだけですね。

後ほど紹介しますが、Timelineなどは、タイミングによってどのアニメーションを再生するのかを制御する機能です。Animator Controllerだと、State Machineベースでアニメーションをどう制御するのかという機能であったり……そういったところを制御しています。

Playable APIの仕組み

このPlayable APIの仕組みを少しだけ紹介します。基本的にはPlayable Graphと、Output、Playableという3つがあります。OutputはAnimatorに対して接続できます。

PlayableのなかにどういうAnimationClipを持ってくるのかや、どのように評価するのか、どのPlayableを選択するのかといったことを行って、その結果をOutputにつなげます。そのOutputの先にあるAnimatorに対して「こうやってアニメーションするよ」という情報を渡してやることで「どのAnimationを再生するのか?」が選択されます。非常にややこしいです(笑)。ツリー構造が使えるので、こういった複数の複雑なツリー構造を立てることができます。

先ほど、「Simple Animationは、全部Playable APIだよ」という話をしましたが、実際はこのようになっています。

Simple Animationは本当に、Animationがあって、その下にMixerがあって、どっちのAnimationを再生するのかを指定するだけの機能です。

持っているState Machineによってはもっと複雑になりますが、一番シンプルなかたちはこういう感じです。Animator Controllerの制御があって、その下にレイヤーで制御する機能があって、その下にAnimation Mixerで制御する機能があります。ということで、ブレンディングやタイミングの調節などを実現しています。

Animation Instancingというアプローチ

Simple Animationなどの「Playableで、もっとシンプルにする」というアイデアはアリなんですが、もしすごくシンプルにパフォーマンスがほしい場合には、Animation Instancingというアプローチも視野に入れたほうがいいかもしれません。

これはシェーダーで、頂点アニメーションでアニメーションを実現するアプローチです。基本的にはシェーダーで全部行うので、Instancingが使えて、すごく効率的に描画できます。とてもたくさんの描画に使えるのですが、基本的には超ローポリ向けです。

この3つのアニメーションシステムをどのように使い分けるのかというと、基本的にAnimator Controllerは、Animator Controllerで制御したい場合に使います。制御負荷はちょっとだけ高めですが、Animator Controllerの部分で制御を作り出すことができるので、そういったことは楽です。アニメーションベースでキャラクターを動かしたい場合には有効です。

Simple Animationは、スクリプトで全部差し替えることで実現します。割り込みやブレンドが多い場合は、こちらのほうがいろいろな意味で楽です。

背景キャラなど、とにかくキャラクターを多く出したい場合には、Animation Instancingが便利だと思います。ローポリ向けなので、使えるケースが限られているところはあります。

Timelineとは何か?

では、Timelineの話をしましょう。今までがAnimationでしたが、Timelineは今までのAnimationとは立ち位置が異なります。

このTimelineという機能は何が便利かというと、Animationの微調整や確認といったものを、再生ヘッドをスライドさせたりして確認できるという点です。

これはAnimationだけではなく、Animation以外にも、ターゲッティングや、もっと別のスクリプトで動く何かなども制御できます。

動きやタイミングを微調整しながら作れるのが魅力の1つです。

タイミングを調整しながら動きを作り込めたり、すでに動いているキャラクターに対して、アニメーションを流し込めます。あとは、複数の動きが連携する表現を作りやすいというのも、特徴の1つですね。

主な用途としてはカットシーンなどですが、Animationを流し込めるという特性によって、いろいろなアイデアが思い浮かびます。

Timelineの構成

ちなみに、Timelineの構成はこんな感じです。

AnimationClipがあるのは相変わらずですが、その先はAnimator Controllerと、TimelineAssetです。Timelineの先はPlayable Directorに流れていて、Playable Directorから複数のAnimatorに対してアクセスして、アニメーションを行います。

この複数のAnimatorというのが、既存のAnimationを動的に流し込める部分です。アニメーションするキャラクターに対して、指定したアニメ―ションを流し込めます。つまり、動的に差し込めるということです。

すごくややこしい説明をしているかもしれませんが、どういうことかというと、動くキャラクターはAnimator Controllerで作ります。そのほうが楽かもしれません。

普通にアニメーションを作って、特定の場所にたどり着いた時に特殊なアニメーションを実行させる。そういった場合に、Timelineは非常に使いやすい機能です。

例えば宝箱を開けたり、取引をするモーションや必殺技などといったものをAnimator Controllerに突っ込むことが多いんですが、必要に応じてTimelineに流し込むというアプローチは、いいアイデアだと思います。

例えば、こんなことができます。

これは、キャラクターを自由に動かしているんですが、このイベントが始まると特殊なアニメーションが始まって、ロボがコーヒーを作ってくれます。こういった、常に動いてるキャラクターに対してアニメ―ションを流し込める、便利な機能です。

他にも、複数のアニメーションを同時に制御できます。確認しながら制御できるので、複数の動きに連携しているものにも使いやすいです。

例えばカメラワークです。ダンスモーションのときにカメラをどう動かしたらカッコいいのかは、けっこう微調整が必要ですので、そういうものに活用したりします。

他にはオーディオやエフェクトですね。あとは、キャラクターがカップをもらう動作や、ロボットがコーヒーを出すなど、そういったものをタイミングを調整しながら作ることができます。

ちなみに、もしダイナミックにTimelineを生成して利用したい場合には、個人的にはPrefabにPlayableDirectorを格納して使用するというアイディアが楽かなと思います。このアプローチならば、Prefabの中にカメラワークやオーディオ、エフェクト等の挙動を内包できるので、動的にバインドする手間が少なくて済みます。

Prefabで多くのバインド情報が格納されているので、自分キャラクターと相手キャラクターだけバインドすれば、あとはきれいに動きます。例えば必殺技のモーションや、ドアを開けるモーションなどは間違いなく楽かなと思います。

今後アニメーションに追加される機能

では、アニメーションの未来の話をしましょう。これまでは、すでに普通に使ってる方もいたかもしれません。ここからは、少しだけ未来のお話です。お話するのは、Animation C# JobsとKinematicaです。

まずはAnimation C# Jobsの話をしましょう。これはアニメーションにカスタマイズを入れる機能です。

何をやるかというと、AnimationのStreamに対して、直接アクセスできる機能です。

先ほど紹介したAnimationClipがあって、AnimationのStreamがあって、その結果スキニングを行うという話でした。AnimationClipがあって、その間にAnimation C# JobsでStreamに割り込み処理を行って、AnimationのStreamに書き込むということができるようになります。

今までは、AnimationのStreamに書き込めなかったので、事後処理でエフェクトを付けていました。これを事後処理ではなく、AnimationのStreamに直接もらって、変更して、書き出して、スキニングして、という流れができるようになります。

これは言い換えると、究極的にはAnimationClipがいりません。

独自ファイルを作って、自分でそのマトリクスを考えて、それをAnimation C# Jobsに渡して、自分でStreamingに流し込んで……といったことを定義しています。

Animation Streamをカスタマイズすることで、どんなことができるようになるかというと、先ほど紹介した特殊なアニメーション、もしくは独自の手続き型アニメーション……例えばDynamic Boneや目線の動き、呼吸モーションや目パチだったり。独自のアニメーションブレンドや完全に独自のマスク機能、IK処理などですね。

Animation C# Jobsの仕組み

どのような仕組みかというと、基本的にAnimation C# JobsはPlayable上で動いてます。

Animation Script Playableに渡すと、そのなかで評価してくれるようになります。つまり、Playableを使わないといけません。Animation C# Jobsによっていろいろなことができるようになります。

このPlayableに渡してどうするかというと、Transform Stream Handleをはじめ、いくつかHandleがあります。Transform Stream HandleやProperty Stream Handleなど、こうした同じ階層のStreamにアクセスすることができます。

もしくは、Transform Scene Handleで、Sceneのなかのどれかの情報を作ることもできます。基本的に、このStreamの情報はAvatar上のものを使います。ですので、Avatarがないと使えません。逆をいうと、Avatarがあると、マトリクスに直接書き込むためのHandleがもらえるので、使えるようになります。

このAnimation C# Jobsは並列処理です。

UnityのWorkerアセットで使うものなんですが、この上で動かすことができます。これは、AnimationのC# Job Systemで、Transformへのアクセスもジョブ上で行ってくれます。

これはバグなのか仕様なのか、ちょっと難しいところなんですけれども、一応パラレルではなくジョブで動いてしまっているので、終了するまでメインスレッドが止まるということもあります。

量が多いと便利です。ただ、量が少ないと、使わないほうがいいという微妙な機能ではあります。上げて落としてみたいで申し訳ないですが、現状はそのようになっています。

機械学習を用いた新しいアニメーションシステム

もう1個、完全に新しいアニメーションシステムで、Kinematicaが追加されます。

これは現在絶賛開発中の機能で、機械学習を使ってアニメーションシステムを構築しようというシステムです。

今まで何度も「AnimationClipで」という話をしていますが、これはAnimationClipベースではなく、ポーズベースのアニメーションシステムです。

期待する経路を軌跡として出して、そのなかから軌跡の情報やその前の状態、過去の状態と未来の状態をもとに、どのコースを選ぶのかをダイナミックに選択する機能です。

Kinematicaのコアなアイデアは、基本的にはこの2つです。

動作には予兆があります。例えば、こうした黄色い線の上を走る場合、どうアニメーションをするのか考えることができます。

この人はけっこうなスピードでダッシュしているんですが、次のこの角度で曲がる場合、どのように動くのか。たぶん足は踏ん張るでしょう。そこからピョンとジャンプするかもしれない。グインと曲がる感じですね。そのように動くと思います。

軌跡がもう少し緩やかだった場合には、おそらくポーズは違う結果になると思います。どのポーズを取るのか、どう動くのかは、スピードや軌跡から考えます。

これを使って次のポーズはどうなるのかがわかるので、その情報をもとに連続したポーズ情報、つまりアニメーションを実現するのがKinematicaの機能です。

この連続したポーズはどう作るのかというと、機械学習を使います。

AnimationClipを最初に渡して、そのAnimationClipに保存されているポーズを全部モーションデータベースに移し込みます。

このモーションデータベースとAnimationClipの情報を組み合わせて、遷移する時にどのように動くのかをがんばって学習してもらいます。あとはその学習結果を入れて、どうやってアニメーションを実現するのかを作っていくわけです。

これは非常にユニークなシステムです。

KinematicaもPlayable APIとして、Animation C# Jobsで動いています。

さっき言ったような「AnimationClipベースではなく、自分ベースで」というのは、これのことです。完全にAnimationClipではなく、自分独自のアニメーションシステムで動かせます。

Unityアニメーションシステムのこれまでとこれから

では、最後にまとめに入りましょう。今回、アニメーションの話ということで、アニメーションの再生・制御、あとはもう少し低レイヤーの話と未来の話をしました。

まず再生の話なんですが、基本的にはAnimatorが基本です。

そのAnimatorにいろいろな情報を渡していくことで、キャラクターのアニメーションを実現しています。その時に、AvatarやRoot Motionなどで、ちょっとした便利な機能を使うことができます。

制御の話はいくつかあります。TimelineやAnimator Controller、Simple Animationなどです。

これは使えるタイミングがちょっとだけ違います。例えば、Timelineは特定のタイミングで特定のアニメーションをしたい場合に有効です。ただし、話しませんでしたが、実はアニメーションの切り替えは非常に苦手としています。

Animator Controllerは、パラメーターを渡してあげることによって、どのアニメーションを再生させるのかを自分で決めさせるシステムです。Simple Animationは、全部スクリプトで行うというものです。

低レイヤーの話を見てみましょう。

Playable APIがあります。Playable APIは、再生するアニメーションの選択・管理をするシステムです。そして、Animation C# Jobsは、どのようなアニメーションを再生させるのかを作るものです。

最後にKinematicaです。

AnimationClipから逃げます。軌跡から次のポーズをどうするのかを自分で選択するシステムです。そのポーズをどう組むかは、機械学習にがんばってもらいます。絶賛開発中です。

ということで、自分からの話は以上となります。本日はありがとうございました。

(会場拍手)