UE4.26.1で開発された『KOF XV』
登壇したのは株式会社SNKのプログラマー呂 朗標 氏。呂氏は中国広州に生まれ、本国でネットワークエンジニアを経験後、2016年に来日。京都コンピュータ学院を卒業後に株式会社SNK に入社し、『KOF XV 』のほか『SAMURAI SPIRITS 』にも関わっています。
講演冒頭では『KOF XV 』の紹介と講演 全体の概要、各セクションの構成が説明されました。
『KOF XV 』は2022年2月に発売された対戦格闘ゲーム。2D格闘ゲームとして長い歴史を持つKOFシリーズですが、 今回は直接ゲームプレイに関わるインゲーム部分ではなく、タイトル画面、メインメニュー画面、キャラクターやモードのセレクト画面、ロード画面などのアウトゲーム部分の開発フローにフォーカス。 アンリアルエンジンによる開発手法が解説されました。
バージョンは4.26.1を使用。他にもアウトゲーム部分にはJenkinsやWwiseを使用している。また、インゲーム部分についても使用したツールなどが紹介された
パッケージ/クックのルール設計
開発が進むにつれて、プロジェクトにはテクスチャや3Dモデル、翻訳データ込みのテキストやデバッグ機能など、製品版に不必要なものも含めてさまざまなデータが増えていきます。これらを製品版に含まないために必要となるのが、クックルール(アセット管理) です。
クック ・パッケージ ・エディタビルド についてそれぞれの違いと役割。これらは全てJenkins で自動化されている
アンリアルエンジンではクックルールを指定するための方法がいくつかあります。講演内ではProject Setting内のAsset Managerカテゴリ やPackagingカテゴリ の各項目、そしてより細かい設定が可能なPrimary Asset Labels などが紹介されました。
Asset ManagerカテゴリではPrimary Asset TypeやAsset Base Classなど7つの設定を紹介
Primary Asset Typeを指定するためには、C++でGetPrimaryAssetId()のオーバーライドが必要とのこと
Packagingカテゴリではクック時に含む、または含まないディレクトリを指定する
Primary Asset LabelsはProject Settingより細かい単位で優先度やチャンク、クックルールを設定できる。開発ではCollectionでの指定をよく使ったようだ
本プロジェクト内では3つ全ての手法を併用しており、Asset ManagerカテゴリによるPrimary Asset Type の定義ではキャラクター・UIなどの大きなカテゴリを、Packagingカテゴリによるディレクトリ指定 ではリファレンスミスしやすい臨時アセットなどを、さらにPrimary Asset Labels ではデバッグ関連や個別のルール外アセットに合わせて活用していると語られました。
アーティストとの協業が目指されたステージ/UI設計と最適化
ステージとUI について、まずはステージのレベル構成が解説されました。Persistent Level下にカメラ、コリジョン、デバッグ機能、エフェクト、サウンド、各種ステージ要素などの複数のレベルが存在しています。
各ステージのパラメータはData Asset を使って管理されています。この中にはキャラクターライトの設定、演出中のライトの動き、演出中のカメラの動きなどが収められています。
アーティストが何度も確認しなければならないステージのライティングは、ビルドの時間短縮のために分散ビルド を導入。3台以上のPCでビルドした場合、通常の半分程度の時間でビルドが完了するとのこと。
製品版用の確認についてはJenkinsで定期的に自動ライトビルドをしてコミットしている
キャラクターなど大量のアセットを扱う場合は、データテーブル で一括管理を行っています。データテーブルはUIが分かりやすく、CSV などの編集しやすい形式として出力可能であり、アセットのリファレンスも持たせることができるので、デザイナーやアーティストにデータを渡すための作業と相性が良いと説明されました。
黄色枠のキャラクターパネル部分の順番もデータテーブルから自動生成しているため、この部分の仕様もプログラマーを介さずに変更できる
データテーブルに限らず、ブループリント全般で困ったこととして、Enumの最初のメンバーがすでにマップ のキーとして指定されている場合、マップは同じキーを持った要素を持てないため、結果としてエディタから新しい要素を追加できなくなることが挙げられました。
開発中にはこの現象に関する質問は非常に多かったようだ
Enumを一時的に他の値に設定する、コピーしてテキストベースで調整しペーストするなどの対策を取る必要があった
このほかにも、UIのテキストなどでテキストスタイルを設定した数パターンのブループリントクラスを用意し、それを継承することで、フォントやサイズをまとめて設定しUI制作の作業効率を高められるテクニックなどが紹介されました。
アーティストの工数削減の手段として汎用アニメーションを流用するため、ウィジェットにはNamed Slot を利用しているとのこと。ただし、やりすぎるとウィジェットの階層が深くなりがちで可読性やパフォーマンスが落ちるため、「加減が必要」だと語られました。
何かの拍子にウィジェットのナビゲーションフォーカスがロストしてしまい、マウス以外の操作を受け付けなくなる問題については、入力用UMGを設定し、そこからフォーカスがロストした場合にSetFocusToGameViewport() を呼び出すことで解決しています。
スライドではブループリントによる処理の実装例が示されているが、実際にはプラットフォーム対応のためにC++で実装されているとのこと
キャラクターセレクト画面など、1Pと2Pで表示が対称になる場面については、2P側のUIを反転表示した後に文字やアイコン画像などの部分をさらに反転させています。これにより、片方のウィジェットを調整するだけで両方のウィジェットに結果が反映できています。
反転部分はブループリントで実装されており、2P側ではX軸のスケールを反転させている
UIより手前にキャラクターが表示されるケースの対応 インゲームの必殺技などの演出において、エフェクトやキャラクターが体力ゲージなどの前に出る表現を行うため、一部のUIは3Dで描画されています。
これを実現するために、ランタイムでのHUDとカメラ距離の再計算やCustom Depth Stencil の使用、HUDにポストプロセスエフェクトを適用しないようにするなどの対応が必要でした。
カメラ距離の再計算を行わない場合の例。演出中にHUDが遠くへ行ってしまっている
距離の再計算は解像度やFOVを使い、比較的簡単な数式で求めることができた
ポストプロセスについては3DWidgetのCustom Depth Stencilを利用してポストプロセスマテリアルの適用をマスクした
ただし、ポストプロセスに関してはFXAA によるアンチエイリアス を除外できていないことが判明し、エンジン改造をしてCustom Depth Stencilでのマスク処理をFXAAシェーダーにも反映させています。
また、このタイトルでは演出中にカメラを激しく動かすために想定外のステージオブジェクトがカメラ映り込む恐れがありました。そのため各セクションと事前に相談し、セーフゾーン を決めた上でステージ班に渡しています。
カメラの前にステージオブジェクトである木などが映り込んでしまった例
黄色い直方体がセーフゾーン、白い四角はバトル範囲を示している
セーフゾーンギリギリまでステージオブジェクトが配置されている
GPU負荷は6ms以下、CPU負荷はドローコール含めて2ms以下に最適化
最適化について、本作ではあらかじめ「GPU負荷は6ms以下、CPU負荷はドローコールを含めて2ms以下」 というステージの処理コストの基準が策定されていました。
この基準を満たす上で呂氏が行ったのは、ほとんどがカリング を考慮したアクターマージ での最適化のみであるとしました。
LOD(Level of Detail)を使ったリダクションも考えていたものの、開発序盤以外には使用していない。また、開発後半はほぼアーティストに任せていたとのこと
カリングは現在カメラに映っていない部分を描画しないことでパフォーマンスを上げる機能 ですが、オブジェクトが多いとカリングする・しないの判断をする処理自体が重くなってしまいます。そのため、複数のアクターをマージすることで負荷軽減を図っています。
格闘ゲームは基本的に前方からのカメラのみが使用されるため、「中央と画面両端からの視点(3箇所)から見ることで映る可能性のあるオブジェクトが大体分かる」と説明されました。
また、UIの最適化についてはウィジェットリフレクタ 機能 を活用し、想定外のUIが表示されていないかどうかを確認していたと語られました。アニメーションなどで見えなくしたものの、消し忘れているウィジェット要素の検出などに役立っています。
キャラクターセレクト画面で、メインメニューのウィジェットがすべて描画されていたこともあったという。ウィジェットリフレクタを使用したことで「なぜ重いのか」が判明した事例
続いて、ロードについての最適化が説明されました。メモリからゲーム内にロードする「AddToWorld」部分ではなく、特にストレージからメモリへとロードするメモリロードの部分が解決すべき問題として挙げられました。
ロードには同期ロードと非同期ロードがあり、同期ロードは速度が早いもののヒッチや画面停止しやすく、非同期ロードは速度が遅いもののヒッチは少ないという特徴があります。
本作では同期ロードと非同期ロードを使い分けており、各画面表示時に最初に見えるものに関しては同期ロードで一気に読み込み、ユーザーが操作しないと表示されない要素は非同期ロードで読み込んでいます。ただし、後者もユーザーが操作した時点でまだロードできていなかった場合は同期ロードをかけています。
バトル前のロードについては非同期ロードを入れるタイミングがなく、「多少画面が止まっても、時間をできるだけ短縮させたい」との要望を受けたので同期ロードを実装したとも説明されました。
しかし、結果として同じフレームで一気に同期ロードし、その1フレームが11秒と長すぎる事態に。特定プラットフォームでは1フレームに5秒以上かかると問題が発生するため、アセットを分割し、一定量ロードしたら1~2フレームのディレイを入れ、次のロードを開始するという回避方法を採用しました。
上が分割前、下が分割後の「Unreal Insights 」でのデバッグ結果
呂氏は講演の総括として、「KOF XV」はSNKのUE4開発タイトルの2作目であり、まだノウハウはそこまで蓄積していないとした上で、「今後もより多くアンリアルエンジンの機能を導入してクオリティを上げたい」と語りました。
質疑応答ではアーティストとの連携について質問され、意思疎通などに苦労したことが語られた
『THE KING OF FIGHTERS XV』公式サイト UnrealEngineを馴染ませる ~THE KING OF FIGHTERS XV における開発事例~
©SNK CORPORATION ALL RIGHTS RESERVED.
アンリアルエンジンにハマり、ぷちコンでゲーム作ってた男。映像編で2連覇したことも。
昔はよくアーケードゲームとかやってました。
一番やり込んだのは「ケツイ ~絆地獄たち~」「戦国BASARAX」あたり。ローグライトゲームとかも好きです。