一般社団法人コンピュータエンターテインメント協会(CESA)は、8月22日~8月24日の期間、パシフィコ横浜にて、国内最大のゲーム開発者向けカンファレンス「コンピュータ・エンターテインメント・デベロッパーズ・カンファレンス 2018」(CEDEC 2018)を開催した。
本稿では、開催2日目の8月23日に実施された講演「UE4で多数のキャラクターを活かすためのテクニック」についてのレポートをお届けする。エピック・ゲームズ・ジャパン鍬農健二郎氏(写真)が登壇した。
本講演では「UnrealEngine4(以下UE4)」で、多くのキャラクターを一度に登場させるためにはどうしたら良いか、主にパフォーマンスの観点から各機能でのボトルネックや改善策の解説が行われた。UE4の基礎的なフレームワークの知識を要する、エンジニア向けの講演である。また、本講演の内容はUE4.20で検証を行ったものとのこと。
「フィールド上にキャラクターが多く表示させると、パフォーマンスが落ちてしまう。どうしたらいいのか」
鍬農氏のもとには、このような相談がよく寄せられるという。そこで、解決方法を伝えるために本講演内容を決めたとのこと。
実際にActionRPGのSampleを使って、キャラクターを多く出すかどうなるかを検証した動画を上映した。100体のキャラクターを表示させたときは60FPSで出すことができたが、1000体登場させると、3FPSにまで下がってしまった。何が起きているのかわからないほどカクついている。このように、パフォーマンスに大きな影響を与えている。このあと紹介する策を施したところパフォーマンスは改善され、30FPSを維持するようになった。
セッションではキャラクターがたくさん登場する場面で、CPUのパフォーマンスを改善する方法が解説された。
▲今回の講演で話すことと、話さないこと。実は、時間の都合で用意したスライドの50%しか解説ができないとのこと。後ほど資料公開されるそうなので、そちらをご参照いただきたい。
本題に入る前に、認識あわせと理解を深めるためにキャラクターやCPUの動作についてのおさらいすることとなった。
▲Characterの基本的な機能。
▲同じCharacterでも、タイトルによって実現する内容が異なる。
▲Characterを動かす際の、CPUの動作。
本講演では、ゲーム側に近いCharacterについて解説を行うため、GameスレッドとTask Graphスレッドを使って処理の流れについて説明していく。
▲60FPSでの動作の流れをタイムラインで示したもの。緑のバーは各スレッドの処理、バーの長さは処理時間を示す。
上のモデルケースは、時間内に処理が収まっているので、遅延がなく理想的である。以下、詳細を解説する。
▲上記の一連の処理が、1フレーム中の実行コストとなる。
このように、1フレーム中にはさまざまな処理が走っているが、これらの処理は主にTickで実行される。
▲先程の1フレーム中に実行される処理は、各ActorやComponentのTick処理が起因となっている。
▲処理する順番はTick Groupで指定することができる。
先程、60FPSのケースについて解説が行われたが、ここからは多くのキャラクターを出すケースについても見ていく。
▲キャラクター100体を出すと、キャラクター100体分の処理コストが投入される。
CPU処理の流れがおおむねわかったところで、次はCPUのパフォーマンス計測についての解説が行われた。
▲計測の方法と条件。
なお、CPUパフォーマンスのTestビルドでの計測については、昨年のCEDEC講演で解説されているので、資料をご参照いただきたい。
▲マネキン1000体を出力した時のDevelopmentとTestのパフォーマンスを比較したもの。同じ構成でも、Testの方が明らかにパフォーマンスが良い。
これは、製品に近い環境で計測することで必要以上な負荷削減を減らすためである。過剰な最適化を減らすことでクオリティを維持するということから、Testビルドでの計測をおすすめしていると鍬農氏。
▲ここまでのおさらいのまとめ。
■負荷のポイントと改善策
ここからはいよいよ本題。負荷削減のポイントを紹介し、それに対する具体的な施策について解説していく。
▲各項目を、Unrealのアイコン数で評価している。アイコンが多いほど、負荷削減に大きく貢献することを示す。
上記アイコンでの評価は独自の評価に基づいたものということなので、実際のパフォーマンスへの影響はコンテンツの内容に依存する。目安としてご参照いただきたい。
まずはAnimationの機能についての解説が行われた。
▲CharacterとAnimationの関連。
▲Animationの処理の流れのおさらい。
▲Animationに関する改善ポイント一覧。上は、本講演で解説が行われるもの。
▲これらは、本講演では解説されないもの。公開された資料にてご確認いただきたい。
では、3つの改善ポイントの具体的な解説を見ていこう。
・多数のキャラクターがアニメーションを行う
多数のキャラクターが登場した際、画面に一部しかキャラクターが映っていなくても、CPUの負荷が高くなることがある。これは、見えていない全てのキャラクターのアニメーションが更新されてしまっていることが原因。
これに対しての改善策は、描画していないキャラクターのアニメーション更新をスキップすることで、コストを減らすことができる。
・移動やアニメーションに伴うBounds更新1
キャラクターが移動やアニメーションを行った際に、ComponentのBounds計算が行われ、Componentの数が多いほどBoundsの計算コストが増加する。
▲多くのコンポーネントを持つキャラクターがたくさん存在すると、アニメーションするだけで多くのコストが発生する。
この改善策は、自身のコンポーネントのBounds計算を行わずに、親のBoundsを使用することで削減が可能である。
・移動やアニメーションに伴うBounds更新2
移動やアニメーション時にComponentのBounds計算が行われる。Skeletal MeshはPhysics AssetからFitするBoundsを作成する。Physics AssetがBoundsの計算をする場合、Physics Assetが持つ全てのBodyを対象に計算が行われるため、Bodyの数が多いほど計算コストがかかる。
改善策は、Skeletal Meshが持つ固定Boundsを使用して、計算コストの削減を実現する。
▲改善策には副作用がある。
次にPhysicsについて。これも、Characterと強く関連している。
▲CharacterとPhysicsの関連を図示したもの。
ここから、本題前にPhysicsについてのおさらいが行われた。鍬農氏曰く、個人的にPhysicsについての情報をあまり見かけないので、少し手厚くおさらいをするとのことだった。内容は、下記資料を参照していただきたい。
Physicsでの改善ポイントは、下記の通り。文字の色が暗いものは本日解説されないものだが、後日公開される資料に掲載が予定されている。
・Physicsのシミュレーションが多い
負荷ポイントは、動いているPhysics Bodyが多い時に、Physicsのfetchコストが増加するというもの。
▲Objectが動いている時と動いていない時の差を、少し大げさに示したもの。
これの改善策は、Physics Bodyの数を出来るだけ減らすことにある。
▲左はデフォルトの状態で19のBodyを持っているが、右はほとんど見た目に影響しないことを考慮して、首にあるBodyを減らして18になっている。
▲削減前後のマネキン1000体を配置した際の、パフォーマンスの違い。
・Collision設定とパフォーマンス
ここでの負荷ポイントは、CollisionとPhysics両方を適用すると、コストがかさむというもの。
改善策としては、Collision設定の“Query Only”と“Physics Only”を使い分ける。
・アニメーションに伴うPhysics Bodyのスケール同期
アニメーションを再生する際、Bone ScaleとPhysics BodyのScaleを同期する処理を行っている。
改善策は、Bone ScaleとPhysics Bodyの同期をSkipさせる。
次に、NavigationとAIについて。
▲CharacterとNavigation&AIの関連を図示したもの。
▲AIを使用したキャラクターが移動、行動する際の処理の流れを示したもの。
ここで紹介する改善ポイントは下記の通り。本公演では一番上にある、重要な一点のみが解説された。
・移動に伴うNav Octreeの更新
キャラクターが移動時にNav Octreeの情報を更新する。移動に伴い、座標更新されたComponentの数だけ、更新が行われる。
▲Nav Octreeの解説。
改善策は、Nav Octreeが持つComponentの情報の更新を無効にする。
▲副作用にも注意。
続いてはMovement。キャラクターの移動についての負荷ポイントが解説された。
▲Characterと、Characterの移動を行うComponentの関連を示すもの。ここでは、移動するためのComponentをCharacter Movement Componentとしている。
▲Character Movement Componentは移動の機能を提供する。歩く以外にもSwimやflyといった移動や、Networkの機能も備えている。
▲Characterの処理の流れについてのおさらい。
▲ここでの改善ポイントは上記の通り。
・静止中の床判定
負荷ポイントは、静止状態で床判定処理を毎フレーム行うため、定常コストに投入される。
改善策は、床判定のSkip。
▲ここでも、副作用に注意したい。
・移動中の床/衝突判定
負荷ポイントは、移動状態で衝突と床判定処理を行うことで、Gameの負荷がかさむ。
これの改善策は、Nav Walking及びSweepスキップにより、移動時のコストが削減される。
▲Navmesh Walkingモードでの注意点にも気を付けたい。
▲完全に設置していない事象への対策。
・移動に伴うComponentの相対的移動1
この負荷ポイントは、移動やアニメーション時にComponentの座標を更新する。移動に伴う相対的座標からワールド座標への変換が発生して、再配置が行われる。Componentの数が多いほど、再配置コストがかさむ。
Componentの数が影響してくるため、数を減らすことが負荷削減の手段となる。
次に、Networkingについての負荷ポイントを見ていく。
CharacterとNetworkingの関連を示したもの。
▲処理の流れについての解説。
▲ここでもいくつかの負荷ポイントと改善策があるが、本講演においては解説がスキップされている。後日公開の資料にてご確認いただきたい。
最後にその他の要素について解説が行われた。
▲主に、ぜひ知っておいていただきたいという3点について解説された。
▲Affinityの設定(Console Only)。スレッドが動作するコアを指定できるのだが、各スレッドがコアを取り合う事象が発生する。
▲Tickを適切にコントロールする。非アクティブなActorはTickを出来るだけ止めるのが望ましい。
▲コンソールコマンドが2つ紹介された。
ここまでにいくつかの改善を解説してきたが、多数のCharacterを活かすためにコンテンツにあわせて機能や設定のON/OFFをする必要がある。必要な機能も動的に切り替えて、無駄のない処理をしなければならない。そして、出来る限りシンプルに設計するよう心がけて欲しいと、鍬農氏が聴講者に呼びかけた。
▲開発終盤で爆発しないよう、出来るだけ開発初期から相談して欲しいとのこと。
(C) 2018, Epic Games, Inc.
会社情報
- 会社名
- Epic Games(エピック ゲームズ)