NieR Re[in]carnationにおけるキャラクター制御について
こんにちは。クライアントエンジニアを担当している向井です。
NieR Re[in]carnation(以後、リィンカネと呼びます。)では、キャラクター制御の設計から実装、バトルスキルアセットの設計・実装・エディター実装、それら実装の各シーンへの導入実装、アプリケーションビルドのCI環境構築など、幅広く関わらせていただきました。
本記事では、主にリィンカネにおけるキャラクター制御についてその概要と、Unityにおける実装方法について説明します。
1. NieR Re[in]carnationにおけるキャラクター制御とは
まずはリィンカネにおけるキャラクター制御について、その概要を説明します。
キャラクター制御では、主に下記の挙動をカバーしています。
- キャラクターの基礎挙動(待機・歩きや走り・指定場所への移動・キャラクター追従など)
- キャラクターの演出挙動(指定されたモーションの再生・タイムライン連携)
- LookAtなどのプログラムでのアニメーション制御
「キャラクターとは何か」というと、ゲーム中に上記の挙動を適用したい対象は基本キャラクターとして扱っています。
リィンカネは大きく分けて「檻」と「物語」、「バトル」の3つのパートからなります。それぞれのパートでの挙動を分解していくと、一部はパート固有なものはあるものの、「歩く」や「走る」などの挙動は、どのパートでも利用します。(「物語」は2Dですが、移動軸を一軸制限したものだと捉えると「檻」や「バトル」と同じになります)
そこでキャラクター制御は、機能の再利用ができるように各パートでできる限り同じシステムを利用するようにしています。またパート固有な機能は、それぞれの機能を持つコンポーネントをアタッチすることで実装できるようにしています。(厳密に言うと、基本的にすべての機能をコンポーネントで開発し、共通のコンポーネントは全キャラクター共通でアタッチしています)
同じものをつくらないようにすることで、開発工数の削減やキャラクターの挙動の品質を一定に保つことができ、また修正も容易になるといったメリットがあります。(一方で、挙動を修正すると影響範囲が広くなるというデメリットもあります。)
また同じシステムを使うことで副次的に、キャラクターのアセットフォーマットも合わせて統一されるので、アセットの管理コストが下がるメリットがあります。
2. キャラクター制御のUnity実装について
リィンカネはUnityを用いて開発を行っています。上記のキャラクター制御をどのように行っているか説明します。
キャラクターの基礎挙動について
キャラクター挙動においてキャラクターの状態管理は重要な要素です。実装の際、たとえば「はしごを登っている状態では重力を一時的にオフにしたい」とか、「スキル演出中はアニメーションの移動値のみでキャラクターを動かしたいため、物理挙動によるキャラクターの移動をオフにする」など、挙動の実装では、ある状態はこの機能をオン・オフにしたい、などといった仕様が頻発します。
そこで状態の管理にステートマシンを用いています(厳密にはステートマシンを入れ子にすることができる階層型ステートマシンを利用しています)。ステートマシンではそれぞれの状態の定義(例えば待機や歩き・走り、はしごを登るなど)と、その状態の際に実行する処理の一覧(例えば特定のアニメーションを再生する、重力を有効にするなど)を管理できるようにしています。また、ある状態から次の状態に遷移するトリガーも合わせて定義します。
リィンカネでは上記のために独自のステートマシン実装を行うことでキャラクターの状態を管理しています。
アニメーション制御にはUnity標準の「Animator + Animator Controller」を利用しています。
「Animator Controller」も内部ではステートマシンを利用しているので理屈上は上記のようなキャラクターの状態管理も「Animator Controller」で実装が可能ですが、状態に詳細にアクセスしづらいことや、様々な独自ロジックをたくさん差し込むような拡張が難しいことなどから、独自実装のステートマシンで状態管理を行っています。
独自実装のステートマシンの状態から再生したいアニメーションを決定し、そのためのパラメータを「Animator Controller」に渡してアニメーションを制御します。MVCでいうところの「ModelおよびController」として独自実装ステートマシンがあり、「View」として「Animator Controller」を利用するような関係になります。
また、リィンカネに登場する地形は比較的複雑なので剛体シミュレーションによりキャラクター移動を実装しています。物理エンジンにはUnity標準の「PhysX」を用いています。地形コリジョンの作成は、背景を作成されるデザイナーさんに、背景データ作成時にメッシュコリジョンも埋め込んでもらっています。
キャラクターコリジョンはキャラクターの体格を元にスフィアコリジョンを用意し、スフィア vs メッシュでシミュレーションしています。キャラクターコリジョンにはよくカプセルコリジョンでキャラクターの形状を近似するケースが見られますが、リィンカネではキャラクターの身長が影響するようなギミックや挙動はないので、より計算コストの低いスフィアコリジョンでキャラクターを近似しています。
また、物理シミュレーションも計算するキャラクターの体数が多くなるとその分計算時間がかかるので、物理シミュレーションが不要なキャラクターには、プログラムから与えられる速度や、アニメーションカーブの移動値でそのまま動くキャラクター挙動も用意しています。
リィンカネはキャラクターの等身や地形がリアルで、いわゆる足滑りを起こすと没入感を損なってしまうため、剛体の速度生成にはアニメーションの移動量を利用しています。こちらは「Animator.OnAnimatorMove」で算出される移動量を利用しています。
キャラクターの演出制御について
リィンカネでは、各所でキャラクター同士が掛け合いを行います。掛け合いなどの実装は大きく分けて下記の2つの方法により実装を行っています。
- 「スロットアニメーション」を用いた任意アニメーションの再生
- Unity標準の「Timeline」を用いた演出作成
1. の「スロットアニメーション」は、任意のアニメーションクリップをキャラクター制御下で行う機能です。Unityではランタイムで「Animator Controller」の遷移を作成・更新することができないため、事前に任意アニメーション再生に必要な遷移情報を一通り作成しておいて、それぞれのステート対してUnity標準の「Override Animator Controller」を用いてランタイムで動的にアニメーションを差し替えることで実現しています。
ただしこの機能だけだと「会話Aとそのアニメーションが終わったら、次に会話Bとのモーションを再生する」というような一連の掛け合いが実装出来ません。リィンカネでは、「イベントマップ」というUnreal Engineでいうところの「Blueprint」のような機能を独自で実装し、その中で掛け合いを実装するようにしました。
より複雑な演出を作りたい場合には、Unity標準の「Timeline」を用いて実装を行っています。「Timeline」は内部的にPlayable APIを介して「Animator Controller」の制御を上書きする挙動をしますが、タイムライン再生中は、キャラクター制御がバッティングしないようにして、タイムラインが停止したら、キャラクター制御を復帰させています。
3. キャラクター制御のためのツール制作
リィンカネでは、キャラクター制御の効率化のために、たくさんのツールを作成しています。そのなかでもキャラクターセットアップツールとデバッグシーンについての紹介と、なぜそのツールを作成したのか説明します。
キャラクターセットアップツール
これまで説明したキャラクター制御は、キャラクターのモデルルートにMonoBehaviour1つアタッチするだけで実現できるわけではなく、複数のMonoBehaviour及び設定ファイルアセットが必要だったり、またヒエラルキーもシステムが期待した階層通りに配置する必要があります。もちろんキャラクターが利用するアニメーションのための「Animator Controller」も、すべて決められた遷移で生成する必要があります。
キャラクター制御のためのセットアップをランタイム上でキャラクター制御の初期化フェーズで行うことで、その手間を省く事もできますが、その分初期化が複雑になるため、ロードに時間がかかるといったデメリットもあります。
セットアップを手動で行うのは作業負荷が高いため、そこでキャラクターのセットアップはツールで自動化して、ランタイムでは1キャラクター1プレハブ読み込むことでキャラクターを動作するようにしています。
また、セットアップの際に元のモデルデータやアニメーションデータのバリデーションも同時に行うようにしています。これにより成果物が本当に正しいデータで納品されているかどうかわかりやすくしています。
ツール制作について個人的な意見として、ゲームで必要になるデータは、下記の理由から、可能な限りツールによって自動化することが望ましいと思っています。
- 作業の効率化になる。また、ツールが出力するので、ヒューマンエラーを防ぐことできる。作業者ごとにセットアップのクオリティのばらつきがなくなり、属人性を取り除くことができる。どの職種の方でもデータさえ揃えばセットアップできるようになる。
- ツールが出力した成果物のみを利用することで、期待しない構成のデータがゲームに入り込むことを許可リスト方式的に防ぐことができる。
- 開発によって構成が変わった場合の対応コストが比較的低く収まるので、ある意味変更に対して頑健性がある。そのため(特に開発中は)積極的に構成変更が伴う実装を行いやすくなる。
ただし、ツールのメンテナンスコストがかかるといったデメリットも当然あります。しかし、特に終盤〜リリース後はデータの信頼性が重要になるため、データ作成を自動化しておくことでデータ不整合による不安要素を取り除くことができます。
キャラクター制御のためのデバッグシーン
最後に、キャラクター制御のデバッグのためのシーンについて紹介します。
キャラクターの基礎挙動や、各コンポーネントによる機能の動作確認には、ゲーム中の、特にキャラクター制御だけを切り出した、専用のシーンを用意しています。基本すべてのキャラクター制御の機能を、このシーン上で呼び出す事ができるようにしています。
このデバッグシーンは、主に下記の目的から制作しました。
- 実装したコンポーネントを単機能ごとの確認・修正のイテレーションを高速に回すため。
- モデル・アニメーションを制作されるデザイナーさんの成果物を、実際にゲームに組み込まれる前に、その挙動を確認するため。
1. については、実装中の機能の確認のために、「プログラム修正 -> ゲーム起動 -> 挙動確認」を繰り返すと、特に「ゲーム起動 -> 挙動確認」に大きく時間を割いてしまい、開発効率を大きく落とすことになります。
ゲームは機能を実装すればするほどそのロード時間が長くなり、その待ち時間が無駄になります。また、確認のためにその機能がゲームで利用されている箇所まで移動するのも非常に手間です。
もちろん、このような確認を簡単に行うためにゲームの作りを工夫するのも手ですが、ゲームを作り込んでいくにつれてその実装も難しくなる傾向にあると感じています。それならいっそのことキャラクター制御とゲームシステムをできる限り疎結合に作っておき、それだけを切り離し、デバッグシーンの要件にあったシーンを実装したほうが楽です。
副次的なメリットとして、ゲームシステムからは切り離しているので、ゲームサーバーやアセットサーバーなど、ゲームが必要とする各種環境の構築が不要になります。(つまりデバッグシーン自体はスタンドアロンで動作します)そのため、開発中にサーバーとなにかしらの理由で接続できなくなったとしても、独立して開発をすすめることが可能になりました。
2. については、デザイナーさんが、例えば「バトルシーンで実際のスキルデータなどのデータが入る前に、スキルで利用するアニメーションおよびスキルの演出データを確認したい」ことや、「檻や記憶シーンに実際に組み込みされる前に、制作したモデルおよびアニメーションを、キャラクター制御込みで確認したい」などの要望が多かったために、開発で利用しているデバッグシーンをそのまま公開しています。
4. まとめ
本記事では、リィンカネのキャラクター制御について、その概要とUnityでの実装方法、また開発を効率的に行うためのツール制作について紹介しました。
キャラクター制御は、ゲームの要件によって実装が様々だと思います。このようなゲーム性においてUnityでの1実装として、参考になると幸いです。
この記事へのコメントはありません。