CEDEC2017 面白かったセッションのただのメモです。
※内容の保証はいたしません(ノω・)テヘ
トリコの動かし方 ~『人喰いの大鷲トリコ』におけるプロシージャルアニメーション技術~
今年の僕のMVS(Most Various Session)。
記事:ファミ通:『人喰いの大鷲トリコ』トリコをリアルに動かすプロシージャルアニメーションとは!?【CEDEC 2017
//!@brief ここからが僕のメモ。
重きを置いたのは、トリコを生き物として表現するということ。そのために、一般に難しいと言われる、動物、巨体、四足、羽毛ということに対してどう向き合いどう対処したか。
大枠のフローは
AI → アニメーション → プロシージャルアニメーション → 物理 → ファー → レンダリング
今回語るのはAIとプロシージャルアニメとファー。
AI部分
まず、設計思想として複雑さよりも調整しやすさを優先した。結果流れとしてはシンプルに、
興味対象の決定 → 興味対象へ移動 → アクション
というフローに統一されている。
興味対象決定は、興味レベルパラメータが、オブジェクトや距離に応じて決定され、興味対象へアクションするとその興味レベルが下がり時間で回復する、というわかりやすいもの。興味対象への移動は、単純にナビメッシュ。ただし巨体なので、侵入可能かどうかのチェックなどは別途行う。アクション選択は、優先度順に候補アクションが実行できるかテストし、できるものを実行。
このようにAIは難しいことはやっておらず、動物っぽさをだしてるのはプロシージャルアニメーション(以下PA)の力によるところが大きいと思っているとのこと。
プロシージャルアニメーション(PA)
PAは足の位置合わせなど、そもそも昔からやっていること。やらないと膨大なアニメーションデータが必要になる上に、そうしたからといってクオリティ担保できるとは限らない。少ないアニメデータでやれば、1つ1つのクオリティはあげられるし、技術的なチャレンジがしやすくなる。
PA適用の設計思想としては、少ないアニメデータ(すべて手付け)を活かすことと、そのアニメーションありきで処理すること、アニメーターがどうすべきか処理を(プログラマと一緒に)考える。アニメータが主で考えるところが珍しいのではないかとのこと。
PAはモジュール単位で適用し、胴体→足→頭→指先の順に決まっている。以下代表的なPA適用例。
歩行姿勢制御
元のアニメーションは真っすぐ歩いてるだけ。そこを背骨をAIが出すパスに合わせて、ベンド処理(曲げる)することで曲がった移動となる。あまりに急な曲がり角(直角)などは、ナビメッシュをカーブ内側を削ってわずかに膨らんで大回りするような工夫をしている。
足運び
まず着地点を決定。着地点は、キャラがいたり、急傾斜地などが除外される。歩行モーションは4つのアニメーションデータで1ループとなる構成がされており、それぞれのアニメーションの切れ目でのみ別のアニメーションへ遷移できる。また、足が接地するタイミングはアニメーションデータに埋まっている。着地点を決めたら、そこまでの最短経路と、元のアニメーションルートとで補正をしていい感じの軌道を作る。腰(ルート)が動いても、足は固定する。足があがってから少しずつ補正してあげる。
姿勢補正
四足それぞれの位置から、1点ドライバー的な位置(四足の真ん中あたり)を決める。それを基準として、胴などの姿勢を補正する。
天井補正
天井の高さを把握して曲げてあげる。
注視処理
最初は首骨からのFKでやったが、動物を観察して、首はあまり曲がらず頭の位置と向きが変わっているだけだと気づきそれに合わせた。獅子舞方式とよんでいる。首の回転軸を首よりも鼻先の方にずらして顔の回転をするようにしたりしている。Unityでプロトタイプして試した。
ここまでの要素が入ったデモ改めて見ると、実際に使っているアニメーションデータは、なんとほとんど基本の歩きだけ。それでも十分に多様な、動物らしい動きに見えるからすごい。くぐり抜けなどは、専用モーションかと思っていたが、そこもPAだった・・。
樽キャッチ食べ
投げられた物理的な軌道の樽を、ホントに上顎と下顎のコリジョンで挟んで食べている。それを実現するためにやっていることは、タイミングと位置を可能な限り正確に合わせること。まず、手から樽が離れた瞬間からの動きで放物線を予測。それに合わせてトリコも準備。トリコにはキャッチしやすい空間領域が設定されており、そのエリアに入ってきたら、そこから詳細な位置合わせ。毎フレーム口先の位置補正を行い樽の正確な位置に近づけていく。樽が近づくほど位置合わせがどんどん正確になっていく。
ファー
ファーの表現法には大きく2種類、シェル法とフィン法があるが、密度上げた表現をするため今回はフィン法。
ファーには風を感じさせる役割がある。実際の鳥を観察すると、あまり風が吹いても羽根同士の摩擦等で、あまり羽根は動かないことがわかった。それをふまえて、風の強さに応じて、羽根の摩擦のようなパラメータを切替ることで、風が弱いときにのみ摩擦が強く羽根はあまり動かなくなり、風が強いときにだけ毛が逆立つような動きをするようにした。
空間の風は、実際に波形データを配置して動かしている。風によるフォースにはランダム値を入れることで、羽根の動きや草ゆれも、リアルっぽいランダムさが生まれる。ランダムじゃないと、きれいにそろって揺れてしまう。
以下主にQ&Aの内容からのまとめ
尻尾
物理シミュレーションで単純に動いており、通常時はPAがかかったりはしていない。イベントなどの少年を助けるときなどに、多少の位置補正はある。
少年とトリコの関係性
物理的にはトリコが親という扱いで、トリコが押されたりすることはなく、少年は逆にトリコに押される。なので、首を寄せてきて少年が撫でる時は、トリコがおおよそいい具合の位置に頭を持っていって、少年が手を合わせてあげることでフィットした動きになる。
足固定による伸び切り問題
腰骨(ルート)が動いても足は滑らないように固定する対応をしている。その場合足が伸び切って変になることがあるが、その場合どうしたかという質問。伸び切らないような動きになるように調整しているだけとのこと。
トリコをもう一回やりたくなった・・。
ニューラルネットを用いたキャラクター制御
4Gamerさんが速攻で記事あげてました。まさか、こんなジャンルの記事が速攻であがるとは・・。
4Gamer:[CEDEC 2017]ニューラルネットがキャラの動きを自然に,処理負荷を低くする? キャラクターアニメーション品質向上に向けた新提案
//!@brief ここからが僕のメモ。4Gmaerさんの記事読んだほうがイイヨ。
モーションマッチングのポーズ決定部分をニューラルネットワークによる学習データに落とし込んで決定する方法。学習してポーズ決定するので、従来のモーションマッチングより省メモリかつ高速に決定処理をすることができる。ディープラーニングに詳しくないのではっきりイメージできてないが、学習後の実機で必要なデータはモーションではなく、ポーズを決めてくれるナニカになっているということか。
概要としては、ニューラルネットワークへの入力として、現在/過去のポーズや経路・操作入力・地形データ等を入れて、学習データから判定し、次のポーズを決定する。
学習データは大量のモーションキャプチャデータ。モーションマッチングではそこに速度や移動方向データがありそれとマッチングして実ポーズデータから決定していた部分が、学習データとして事前処理されランタイムでは省メモリの学習データのみから、ポーズが決定される。
学習データから、最適なポーズを決めるときに補助するのが、フェーズファンクションと呼ぶ歩容の位相パラメータ。中身は単純で、いつ足が接地するかを周期的に決めるというもの(0.5sec後に右足接地、1sec後に左足接地みたいな)。1周期中の特定4ポイントのポーズ(キーフレーム)を学習データから決定することで、特定時間のポーズをCatmull-Romスプライン補間で求められる。(Catmull-Romスプラインは4つの制御点が見つかれば補間可能。)
状況に応じて、かがんだり、バランスをとったりさせられる。それには、環境データからとるべき動きモードを取得して入力として渡している。
Catmull-Rom補間で処理コスト1.8msec、メモリ10MBでやれるので実用的とのこと。軽いとはまだいえないが、並列処理で、キャラ数が増えてもコストが増えないならありえなくはない。
問題は、任意の見せたいポーズをださせるとかが難しい。また、4つのキーポーズを決める計算コストはまだ高い。
フェーズファンクションが2足歩行の規則的なものを前提とした作りなので、フェーズファンクションをカスタマイズするなどして多足や不規則な動きに対応をすべき課題などがある。
モーションマッチングのつくりかた
モーションマッチング実際に作ってみました、その際に出た問題と、それにどう対処したかの具体的な内容。
モーションマッチングは、ポーズマッチングと軌跡マッチングでマッチングされる。
軌跡マッチングでは、入力による移動したい方向のパスと、それまで動いてきたパス、モーションのルート移動によるパス、それらとマッチングして決定される。
ポーズマッチングでは、ジョイントの位置と移動速度ベクトルなどとのマッチングで決定される。
問題となったのは、ジョイントの移動方向(スイング)と一致してないポーズへマッチしたり(ポーズ自体は近いが滑らかな遷移にならない)、入力軌跡と一致しない、その反映が遅いなど。
基本的に対処は、マッチングのアルゴリズムに手を加えて、調整。特定方向へのジョイント移動はマッチング結果にペナルティを課す。軌跡をあわせるためにモーションワーピング(モーションルート移動方向を回転等で調整すること)。
やってみた所感として、実装自体は難しくないが、デバッグが難しい、データ自体が大事、という感想。デバッグが難しいのは、変なポーズでても要因がわかりにくいことや、パラメータ調整がすべての動きに影響してしまうことなど。
上のセッションとも合わせて、まだクオリティ担保が難しいのにかかわらず、コントロールもしずらいので、気軽に実用にはまだならない印象。
Cygames における次世代ハイエンドコンソール向けゲームエンジンの開発 ~最高のコンテンツを支えるゲームエンジン~
大きく、エンジン、ゲームプログラム、コンテンツの3つの開発部分に分けて解説。
エンジン開発部分
テスト駆動開発を徹底して行う。徹底が難しいので、実装方法(ワークフロー)を限定して強制する。
ワークフローは、すべての作業を専用コマンドへ集約。build,test,platform指定など。集約させることで使うツールを多様化させずにシンプルなワークフローを実現する。
言語も限定。ランタイムは基本C++、ツールはPythonと決める。Pythonなのは用意されているモジュールが多いから。
コードはC++はclan-format、Pythonはpep8/flakeで自動整形。コード規約論争に終止符を打ち、コードの中身に集中してもらう。
ワークフローが限定されてるのはわかったが、テスト駆動がどう強制されてるかはいまいち不明。自分がテスト駆動嫌いな人なので、これならやれるってゆう具体的フロー見てみたかった。
ゲームプログラム開発
とにかくイテレーションをいかに早めるかが重要。ということで、実行時コード編集&反映を可能にするため、Runtime Compiled C Plus Plus(以下RCC)で対応。
参考:Getting started with Runtime Compiled C Plus Plus
具体的な実装は、RCC用のRCCObjectクラスを継承して作る。関数コールを静的なリンクじゃなくするため、inlineかvirtualのみにするなどの実装時の制約アリ。当然vtable解決のランタイムコストなどはデメリット。また、実行時のオブジェクト実体更新のために、シリアライズ処理の実装も必要。今丁度、すこし制作中のモノがあるのでそこに入れて、一回使ってみようと思う。
それから、イテレーション早める次のポイントは、ビルド時間を短縮すること。基本的なことをちゃんとする。余計なヘッダーインクルード削減、templateによる実コード展開が多くなるのを気をつける、など。また、ハードウェア性能を上げる。SSD必須。結果としてRCC実装の制約(リンクが少ない)もビルド短縮に貢献。エンジン含めたフルビルド、30秒。アプリプログラムだけなら5秒。
コンテンツ実装
任意のバージョンのアセットがとりやすい(=早い)ような環境を作る。そのため、バイナリはバージョン管理せず、中間データとメタデータ(依存関係情報含む)のみをバージョン管理。実機用アーカイブが必要なときに、バイナリコンバートとアーカイブを必要なリソースに対して行う。ローカルにはバイナリのキャッシュを置くことでコンバート時間を削減する。
アセットビューワーでは、オーサリング(Mayaシーンファイル)編集で即時反映できるように。そのために、中間データも専用のバイナリフォーマットにしており、素早くメモリ展開できるファイルとしておく。FbxやColladaは汎用だが重い。またプレビューモードで不必要な描画オプション等を切って高速にする。
Perception Tree ~Behavior Treeを応用したお手軽、柔軟な環境認識システム~
ゲームAIエンジンは、ゲーム固有のものに依存性が高くなりがちで、汎用性にかけることが多い。バンナムではそれを汎用エンジンとして作る試みをしていて、そのエンジンがMunchkin(マンチカン)。Perception Treeは、そのAIエンジンの環境認識部分に取り入れている仕組み。
環境認識は、能動的に探索するPull型と、コールバックイベントなどで通知をうけるPush型があるが、能動的に探索する法をどうするか、をPerception Treeという仕組みで実現。
環境認識は、CryEngineのTPSやUE4のEQSなどのシステムがすでに有名。簡単にいえば、評価点の生成方法やクエリー方法の種類などを定義して、その組み合わせで、必要な環境情報を取得・評価する方法。基本フローは、情報取得するポイントの生成、そこから必要な点のみにするフィルター、そして最適な点をみつけるスコアのフローで最適な環境情報は決まる。
Perception Treeでは、このクエリーなどの組み合わせと評価の部分を、Behavior Treeの仕組みを流用して、汎用的かつコストを安く仕上げている。たとえば、Behavior Treeには、子ノードを評価するのにSequenceとSelectという評価方法があるが、Sequenceで多段階的にいくつかのクエリー条件を順に適用させたり、Selectで優先度順で当てはまるもの1つをクエリーしたり、といったことが汎用的に組める。また、Behavior Treeのシステム(ツールなど)をそのまま流用できる(Behavior Treeのカスタムノードとして拡張)ので、コストが安く実装できる。
既存の環境認識手法が、条件等を柔軟に設定できるになって汎用化されてきたのが、さらにその組み合わせ定義まで汎用化されて、しかも安くてわかりやすいので結構有用に思えた。
RE ENGINEでのゲーム開発を支えるMacro(Plug-in)機能の紹介
内製エンジン「RE ENGINE」を拡張するための仕組み「Macro」を作った話。DCCとエンジンをつなぐためのDCCツール側のプラグインの話かと思いきや、エンジン機能自体を拡張するためのプラグインの仕組みだった。いい意味で予想と違ったが面白かった。
MacroとはREエンジン上でPythonで実際にコードを書いて行単位やファイル単位で実行したり、それを機能としてエンジンに組み込める仕組み。PythonコードからRE ENGINEの機能(API)呼び出しをできるようにしている。作った機能は、ボタン化などしてエンジンUIに組み込める。
なぜ内製エンジンをこのようにフレキシブルな拡張ができるようにしたかというと、エンジンの保守はしたいので、エンジンコードをアプリ実装者などに触ってほしくはないが、初期だと機能が足りないのも事実、この間をとりもつため、必要な機能が拡張しやすくかつ保守しやすい仕組みを用意した形。
これにより、大量のアセットに対して、一括で行いたいちょっとした処理(テクスチャサイズ一括変換とか)や、いつも行う一連のリソースセットアップ処理(モデルやマテリアルの設定とか)などを、Macro機能として実装して自動化できた。
実装の中身は、IronPythonという.NETからPythonを実行できるライブラリと、AvalonEditという.NETで使えるテキストコントロール。AvalonEditは、補完やSyntax Hilightを効き高機能。これを、変更やエラー対応をまとめられるように、エンジン機能呼び出しモジュールとしてラップ、IronPython呼び出し部分をラップするなどして、Macro利用者(機能作成者)は、1つのPythonモジュールを意識するだけでいいシンプルかつ保守しやすい形にして実装。Python(インタプリタスクリプト)は、実行時までエラー不明なので、そのエラー発生箇所を局所的にまとめらえるのが大きい。
Macro実装しやすい環境を提供するため、ドキュメント(Reference)の自動出力なども行っている。
このMacroの仕組みがあることで、TAや若手エンジニアなどもちょっとした機能を作って、すこし便利なプロトタイプなどが増えた。
自分の感想。エンジンを使っていると、かゆいところに手が届かない、あの機能がないなどゆうことはよくあること。その際にちょっとしたコストで拡張できる枠組みがあることは開発スピードをあげることができそう。この仕組によってできる自由な拡張の管理と、エンジン側が使えるように拡張・保守対応するコストが懸念。
その他見たいセッションのメディア記事へリンク
ゼルダは終わってからが本番。SNSもほんとゼルダの話ばかり。たしかにすごく良さそうだけど、上記したセッションもヨカッタヨ!
『ゼルダの伝説 ブレス オブ ザ ワイルド』におけるフィールドレベルデザイン ~ハイラルの大地ができるまで~
記事ありすぎ・・。
ファミ通:『ゼルダの伝説 BotW』自然と寄り道してしまうレベルデザインのカギは、“引力”と“地形”! 魅力的なハイラルができるまでを解説【CEDEC 2017】
IGN:「ゼルダの伝説 BotW」、こうしてオープンワールドの見本となるような作品ができあがった
4Gamer:[CEDEC 2017]「ゼルダの伝説BotW」の完璧なゲーム世界は,任天堂の開発スタイルが変わったからこそ生まれた
Gamer:【CEDEC 2017】「オープンエア」の世界はこうして作られた―「ゼルダの伝説 ブレス オブ ザ ワイルド」におけるフィールドレベルデザインの講演をレポート
『ゼルダの伝説 ブレス オブ ザ ワイルド』のプロジェクト運営 ~試作から製品までシームレスに!~
データに紐づくタスク管理ツールで骨組みから作るオープンワールド「ゼルダの伝説BotW」のプロジェクト運営
コメント