Unite2015で公開されたRépublique Tech Demoをチェック!Unity5向けのライティングやプロジェクト構造を読む
先日Unite2015で公開されたRépublique Tech Demoについて解析していこうと思います。
目次
Républiqueとは
République(以下リパブリック)とは、フランス語で…意味は知りませんが、とにかくiOS及びPC(Steam)向けに販売されているステルスゲームです。
ゲームを開発するライアン・ペイトン氏は元々小島プロダクションでメタル・ギア・ソリッド4のアシスタント・プロデーサーを努めたり、Microsoft Game Studios行ったりと中々にアグレッシブな御方です。
【E for All Expo】KONAMI ライアン・ペイトン氏『メタルギア ソリッド 4』は映像や音にこだわり抜いた“本物の3Dアクション” - ファミ通.com
Unite Japan開幕、基調講演でライアン・ペイトン氏が語った“リッチなモバイルゲーム”に挑戦する理由とは? - ファミ通.com
【CEDEC 2011】国内海外のゲーム開発現場を見てきたライアン・ペイトンが語る日米ゲーム制作事情 / GameBusiness.jp
このゲームはヒロインを直接操作するのではなく、ヒロインに対して目標ポイントへ移動してもらう遠隔操作タイプのステルスゲームです。プレイヤーは監視カメラをハッキングして視界を確保、電子ロックや色々なギミックを駆使してヒロインを守りながらステージを進ませます。
その間、何気ない会話やキャラクターの持つメモ・張り紙等にストーリーを読み解くヒントがあるみたいですが・・・・・・・・まぁ、その・・・日本語版に期待です。
このリパブリックの一部のアセットが今回Uniteのタイミングで公開となりましたので、今回せっかくなので解析してみようと思います。
ちなみにファイルサイズは1.2GB(Ver 1.2時)です。
プロジェクト/ファイル管理を読む
プロジェクト構造については、Uniteで発表された資料から紐解くことが出来そうです。Uniteの資料一覧のRebuilding République in Unity 5よりダウンロード出来ます。pdf
モデル(fbx)は地区で分割して管理しているみたいです。マテリアルやプレハブは…命名規則がちと分かりません。
ちなみに、該当のアセット(プレハブやテクスチャ・モデル・マテリアル)がシーン内のどの部分に使われているかを判断するには、アセットを右クリックしてFind Reference In Sceneを使います。
またリパブリックのエディター拡張として、シーン内で使用しているテクスチャ・メッシュ・マテリアルの参照数をカウントし、一覧表示する機能を使用していました。
同時にシーン内で使用するテクスチャやメッシュから最大メモリ消費量を算出するっぽいです。この拡張は中々に実戦的です。
シーン構造を読む
シーンのトップ構造は、まず5つのパーツに分解出来ます。
実際には敵を総合管理・ゲーム進行をコントロールするGameControllerやUI等も含まれると思われますが、今回のデモには含まれておりませんでした。
Collisionは本当に当たり判定のみを管理します。非常に大雑把なコライダーを設定しており、また壁・小物・天井・床といった区分で分割されています。Navmeshでキャラクターが動くことを考えると、フレアの表現・敵キャラクターの視界判定といった用途で使用されている可能性が高い気がします。
Artはライト・メッシュ・ReflectionProbe・その他諸々です。見た目を変更したい場合や、見た目について知りたい場合はこの項目が参考になります。
Designはこのゲームにおけるギミックを制御しています。リパブリックは監視カメラを使いプレイヤーを導くゲームです。その監視カメラの制御について、このDesign以下で行われます。実際はドアの制御や他のギミック等もこの項目で制御すると思われます。
なおiOS版と異なり、監視カメラの切替は「コライダーの範囲内にヒロインが入ったか」で行っています。監視カメラは「コライダーの範囲」「カメラ」のセットで大量に配置されており、各々が独立しているため、ステージを増やしやすくなっています。
Masterはキャラクターを管理しています。キャラクターとは、ヒロインだけでなく敵キャラも入っているっぽいのですが、敵2体には何もスクリプトが設定されていなかった為、単なるMOD要因なのか実際の敵なのかは不明です。
Audioは音を管理しています。ステージの至る所にある効果音や環境音を、これで管理しているっぽいです。
音には2D向け(環境音)と3D向け(効果音)の2種類のミキサーを使用しており、これで全体の音量を調整しているみたいです。
シーン内オブジェクトの参照関係は大体こんな感じです。Trigger(当たり判定)/Camera_view(カメラを操作する)/Camera/camera_gamevis(監視カメラのモデル)は1セットで大量に(28個)配置されています。
Hope_ColliderがTrigerの中に入ると、Camera_viewが起動し他のcameraやcamera_gamevis、あとaudioに対し何やかんやする感じです。
ArtとCollisionは挙動のサイクルには全く入っていないので、ゲーム自体の挙動を解析する上ではそこまで注目しなくても問題無さそうです。
ライティングを読む
ライティングは流石PC向けで豪華です。ライト数でコストが跳ね上がらないdeferred renderingを使用し、これでもかと言うほどライト(しかもリアルタイム!しかも比較的重いスポットライト!)が配置されています。もはや電球1個にライト1個のレベル。
さらにReflectionProbeを各部屋毎に配置し、部屋に入ったヒロインを部屋の色に馴染ませる工夫もされています。(どちらかと言えば、室内を暗くするための措置かもしれませんが…)これはLightProbeの変わりの役割も持っているのでしょうか…?LightProbeはありません。
光の発生源の尽くにフレアを配置しています。これで光の滲みを表現する魂胆なのでしょう(その発想はなかった)。ただし、フレアのファイルがmissingなので、実際にどのように光るのか確認する事はできません。
蛍光灯などの一部のモデルにはEmission(自己発光)を設定し、自分で光るように設定しています。ただ、輝度は限定的に設定されており、基本的に光源はライトから発生するように設定しています。
天井はCastShadowsがTwo Sidedに設定されており、片面しかメッシュが貼っていない場合でも影を作ってくれるようになっています。これで天井上からステージに物を色々と配置する際、roofレイヤーを作って非表示/ロックしなくても良いので楽で良いです。
モデルは大体StandardShaderの物理ベースレンダリングを使用して作成されており、SHADOWGUNのようなシェーダー無双はありません。その辺りは(デモから排除していなければ)凄くシンプルに作れるって事でしょうか。
ちなみに、コレはPC向けなんで良いですが、モバイル向けに作るならライトは焼いたほうが良い気もします。
コンポーネントを読む
このプロジェクトは想像以上にシンプルな物です。殆どのコンポーネントはシンプルに作られておりしかも大体自己完結しているため、とにかくシーンに配置しまくればステージが作れるようになっています。
このシーンでとりわけ重要なのはこの5つ。
- Agent:プレイヤーを制御する。基本的にNavmeshAgentの取得するパスを使用して移動するが、移動自体はAnimatorのコールバックで行う。移動先の設定もコイツが行う。
- CameraRotater:ユーザーが監視カメラを回す。画角はInspectorで指定した値を使用。
- KeyboardControl:キーボード入力を管理。CameraRotaterはココからパラメータを取得する。
- CameraSelectionVolume:コライダーに入ったらカメラをONに、出て行ったらカメラをOFFにする。SelectableCameraを使用。
- FramePlayerOnEnable:Enable時にプレイヤーの方を向く。その際、CameraRotaterを使用。それ以外にも関連オブジェクトのon/offはこのコンポーネントが行う。
その他。
- FootstepPlayer:足音の管理を行う。足の座標を取得するのにTransformを使用する。トリガータイミングはAnimation。
- ActiveByCounter:不明。何か足したり引いたりする物ですが、何処からも呼ばれていないので何に使うのやら。
- Light_Lerp_Sin:光を点滅させるやつ。
- AnimatedCaustics:クッキーをアニメーションさせるやつっぽい。
コンポーネントを探すには、検索バーにコンポーネント名を正しく入力すると、該当のコンポーネントを持つオブジェクト一覧が表示されます(継承元クラスを指定すると、継承先クラスも含めて表示してくれます)。
この点においてはUnity5とUnity4であまり違いはありません。
キャラクターを動かす部分を読む
キャラクターを動かす部分を読んでみます。要するにAnimatorとAgentについてです。
まずAnimatorを確認すると分かる通り、Apply Root Motionの部分がHandled by scriptに変化しています。これは、OnAnimatorMoveメソッドをAgentが持っているからです。こ唸っている場合、Animatorではなくスクリプトでキャラクターが動いています。
Animatorの中身は凄くシンプルに作られています。Half turnにトリガーが入ると180度ターン、turn left/ turn rightで90度ターン、Walkで歩く。後は実際のパスと現在の向きを見て、アニメーションを決定…といった感じでしょうか。
StateMachineBehaviourも無いので、非常に分かりやすくスッキリしています。(本当は使ってることを期待してたのですが…)
スッキリしていないのは、Animatorの持つAnimationの中にEventが紛れ込んでいることです。これは歩行や向きを変える際に足音を鳴らす動作で、Animationに入れるのが一番良いのは間違いないのですが、何処から呼ばれているのか一瞬分からず少し困るかもしれません。
キャラクターの移動自体については、NavmeshAgentでパスを割り出して決定します。このNavmeshAgentに移動先を指定しているのは、Agentです。
やり方はいつもの通り、クリック位置からRayを飛ばして当たった所をAgent.destinationに渡すだけなのですが、クリック判定に"Fire1"を使っている所に何か暗黒的なフォースを感じます。
本当は壁添や障害物付近でも特別なアニメーションを行う事が予想出来る設計ですが、残念ながらデモには歩行しか含まれてません。
この辺りの設計はUnity4からあったので、素直にUnity4プロジェクトを移植した結果なんじゃないかなと思います。
感想
他にも色々と見るべき点はあるかもしれませんが、とりあえず(自称)プログラマーの自分の目についた所はこんな感じです。全体的にUnity4時代の機能を素直に使いつつ、Unity5のグラフィックで作りなおしたといった印象です。
グラフィックやエフェクトの設定方法(エントランスでの光の設定)、モデルやマテリアルの作り方等、人によっては色々と得られるかもしれません。
要望があれば他のプロジェクトも解説しようと思います。
(オマケ)プロジェクトをサクサク読む
このプロジェクトは非常に大きいので、読むのも一苦労です。なので、サクサク読む為に少し小細工を使います。
まず重い原因の一つ、建築物のAtriumと悪魔の塔Terminusを非表示にしてしまいます。解析には何の問題もないのでサクっとやってしまいます。Atriumが見たい場合は、BrigとTerminusを非アクティブにします。
次に、Gizmoの表示を最小限にします。Gizmo単体ではそこまで重くはなくとも、該当のオブジェクトツリーの持つGizmo全部が表示となると、結構な負荷になる事があります。
シーンのGizmoを開いて、不要なやつは全部OFF(コンポーネントが閉じてる扱い)にします。ガチ不要なら3D Gizmosのチェックを外してしまいます。
ついでにSkybox・Flare・ライトもオーディオも全部オフにしてしまいます。必要ものだけONにします。
次に実行時の負荷を下げます。
このプロジェクト、初期版はbatces(旧名ドローコール)が10万、setpass(新しい指標)8000とかアホみたいな数値をたたき出していました。DirectX9相当GPUしか積んでいない自分のPCでは、動かすのも一苦労な負荷です。
何故こんな事になっているかと言うと、答えはすごく簡単で、dynamic batchingとstatic batchingがoffになっていた事と、occlusion cullingが上手く設定できていなかったからです。というか、何故設定していなかったし。*1
occulusion cullingもちゃんと設定します。初期状態ではoccludee static*2しか設定されていなかったので、視錐台カリング的な挙動しか期待出来ません。ちゃんとoccluder staticを設定して、遮蔽物を設定することで、表示範囲を狭めることが期待出来ます。下はoccluder staticを設定した場合と設定してない場合。
ついでにReadmeに書かれていることですが、quality settingsのクォリティを下げると大分軽くなります。自分は下から2番めくらいに設定して色々と見ています。