UE5の手探りゲーム最適化
はじめに
Steamにてゲームリリースのために行った、UE5ゲーム最適化について記載しています。
主に、調べて出てきた内容や実際に試してみた内容をまとめています。
もし、「これは最適化にはならない」、「この情報は違う」、「こんな最適化方法もあります」などありましたら情報提供をよろしくお願いします。
環境
UE5.3を使用
この記事について
X(旧:Twitter)でポストした内容を箇条書きにまとめたものとなります。
内容は飛び飛びになっていたり、文言のまとまりがない場合もありますのでご了承ください。
※※※注意※※※
「この最適化を全てやれば軽くなるぜ!」みたいなものではありません。
それぞれのゲームに適切な最適化を施すのが重要です。
「逆に必要なかった」、「逆に重くなった」などあり得るので、一つ一つ設定しては動作検証をするなどの手探りが必要なものとなります。
ぶっちゃけゲームが重くなければ、むしろやらない方が良いです。
その他
この記事内では最適化の設定について直接設定していますが、
可能であればゲーム内の「設定画面」にてON・OFF切り替えたり、低・中・高などの設定でユーザーに選んでもらえるようにした方が良いです。
最適化
グラフィック関連
Lumenについて
LumenはUE5ではデフォルトの設定になっていて、容易にきれいな光の表現をしてくれます。
ただし重いという意見もあり、確かにOFFにすることでかなり軽くなります。
ゲーム画面のクオリティにかなり影響あるので、OFFにするのは最終手段かなと。(もしくは最初から割り切ってOFFにして、PostProcessで頑張って調整するとか?)
テクスチャサイズ
テクスチャの最大サイズを変更する。画像の例では元々のサイズが2048のもの1024に指定、4Kサイズのであれば結構効果はありそう
ポリゴン数の確認
統計からポリゴン数の確認をする。 「Tris」がポリゴン数で、「Sum Tris」が合計のポリゴン数らしい。 2000から3000までが理想 5000を超えると重たくなり始める 10000を超えると問題が起こり始める とのこと。
ポリゴン数の削減
メッシュのポリゴン数を減らす。 50%に変更することでポリゴン数が約半分に。 少しメッシュが崩れたりするため注意。(例はNaniteのメッシュ)
LOD設定
NaniteでLODは勝手にいい感じに行ってくれるが、カスタムでも設定可能。 どうしても微調整したいときには良いかも。
LumenMeshCard
「r.Lumen.Visualize.CardPlacement 1」のコマンドで確認可能。
メッシュのカードをgroup IDで一つにまとめると軽量化になるとのこと。
ビルはBPで作成されているのでアクター内のメッシュに対してまとめて設定。 別のBPに対して設定する際、同じ番号にしないよう注意。
「【UE5】LUMENMESHCARDってご存じ?」の記事がとても分かりやすかったです。
CastShadow
PointLight、DirectionalLight、SkyLightの「Cast Shadow」をOFFにする。 かなり軽くなるが、影表現などのクオリティに影響してしまうためご利用は計画的に。
無駄にPostProcessを追加していませんか?
この表現はこのPostProcess1、こっちの表現はPostProcess2とか無駄に分けている場合はなるべく一つにまとめること。
アンチエイリアス手法を変更
アンチエイリアスは、ピクセルのギザギザを目立たなくする処理。
処理の軽さは TSR << TAA << FXAA < None デフォルトだとTSRなので重いのであればTAAに変更。
コリジョン関連
不要なコリジョン削除
無駄コリジョンをなるべく減らす。 ビルの看板などプレイヤーがぶつかることがないものを全てNoCollisionに。 FPS的にはそこまで変化なし・・・。まぁやらないよりやっておいた方が良いということで。
コリジョン設定
BoxCollisionやSphareCollisionなど追加した場合、コリジョン設定で必要のないものはなるべく「無視する」にかえておくこと。 実は裏でとんでもない回数で接触判定が動いている可能性もあるので。
BP関連
不要なTickを無効化
BPのアクターの「Start with Tick Enabled」をOFFにしておく。 Tickが無効になることで軽量化に繋がるとかなんとか。(本当なのか・・・?)
Tickをなるべく使わないように、ということにも繋がるので良しとしよう。
バインドについて
Widgetでよく使用する便利な機能のバインドについて。 忘れがちだが、バインドは常に呼び出し処理が動いているので使い方を間違えると重くなりそう。時間表示などリアルタイムで更新表示が必要であればしょうがないけど、リアルタイム性が求められないものであれば毎回セットする形式が良い。
WidgetBlueprintのTickを無効化
WidgetBlueprintのTickを無効化。 NeverにすることでTickを停止できるが以下の機能が制限される。軽量化にどこまで影響あるかは不明。
・Widget Animation
・Latent Action
・Native Tick
・Blueprint Tick
WidgetBlueprintのVisibility
WidgetBlueprintのVisibilityについて。
・Visibilityが最もコストが高い
・表示判定不要ならNot Hit-Testableを利用
・表示しないならCollapsedが良い
大量にWBを使用するなら効果ありそうだけど小規模開発ならそこまで必要ないかも
ライト関連
ライトの数は少なくする
ゲームのクオリティに直結するが、なるべくライトの数は少なくする。(多ければ多いほど重くなる)
画像例のビルのBPではライトが大量に使われていたので削除して一つにした。
MaxDrawDistance
ライトのMaxDrawDistance値を設定して、離れたらライトを消すようにする。 遠いライトやプレイヤーから見えないライトをなるべくOFFにするなど、BPで制御するのもよさそう。
スカイライト漏れ
UE5.1以上?であれば使用可能な機能。
PostProcessの「スカイライト漏れ」を設定することで室内を明るく設定できる。数字を挙げれば暗さが軽減できる。
ライトを置く個数を減らせるため結果的に最適化に繋がる。
ライトの設定
PointLight、SpotLightはなるべくStaticで設定。 ライトは少なめで重ならないように注意し、Stationaryのライトを設定した場合は5個以上重ならないようにすること。ライトに×マークが出ている場合はオーバーラップを意味する。
ライト情報まとめ
・Directional LightはCascaded Shadowで調整
・Point Light、Spot LightはなるべくStaticで。動的に配置するときもなるべくCastShadowさせない。
・Stationaryのライトの重なりは注意(5個以上重なると×マーク出る)
Real Time Capture
「Real Time Capture」をOFFにしてみる。 どこまで最適化に影響するかだけど、OFFにすることでスカイライトのリアルタイムの光の反射がなくなる。 夕方や夜などに明るさが変化するゲームであれば必須だけど、使用しないため一応切っておく。
MetaHuman関連
クオリティ設定
MetaHumanをなるべく「LowQuality」でインポート、それでも十分高クオリティな気がする。 テクスチャに対してプロパティマトリクスからまとめて「Maximum Texture Size」を1024か512に設定(デフォで4kサイズとでかいので)
LOD設定
MetaHumanのBP内にあるLODSyncの設定。 デフォルトで勝手にLODはやってくれるが、近くに複数体MetaHumanがいると流石に重い。 LOD最小設定の数値を変えれば少し荒いが軽くはなる。 4は許容範囲だけど、5は荒すぎる・・・(ゲームのお好みで調整しましょう)
髪の毛の物理シミュレーション
LOD設定によってそもそも揺れない状態もあるが、個別に髪の毛の物理シミュレーションをOFFにすることが可能。髪の毛が揺れがなくなるが、わずかに軽くなる。ものによっては最初からOFFになっているものもあり。
MetaHumanのHairの物理シミュレーション設定が2つ存在することがあるので注意。 Group1、Group2のように2箇所で髪が揺れる設定がある。 画像のイメージで言うとトサカ部分と横髪部分にあたる。
DelayをかけてSpawnする
キャラクター作成時の注意点
Metahuman作成時にはLODに注意。使用する髪型や髭によってはLOD1と2しか用意されていないので、なるべくLOD8まであるものを選択。髪型や髭の選択時に注意マークがでているので、自分自身が作るゲームに合わせて選択しよう。(UE5.4ではLOD8のものの対応が増えている)
骨の数
Metahumanが重い理由の一つとして骨の数が多いという原因がある。顔の骨の数が多い。 表情などを利用しない人はBlenderで削除してしまうのも手だと聞く。
LODにてBoneの表示数制御は行ってくれているので、ある程度LODが多いとき(遠いとき)は負荷軽減にはなっています。
各種LOD
MetaHumanの服をよく見ると紐やらフードが揺れている。 どこまでゲームの負荷に影響があるのかは分からないけど、とりあえず揺れないように設定。 LOD設定0~1は揺れて、2以上に設定すると揺れなくなる。LODSettingsファイルでも設定可能。
MetaHumanのCommonフォルダにLOD設定ファイルがあるのでこちらのファイルを弄れば、全MetaHumanに反映してくれるので便利。
Face_Archetype_LODSettings ⇒顔部分のLOD MetaHuman_Clothing_LODSettings ⇒服周りのLOD MetaHuman_LODSettings ⇒体(肌)部分のLOD
Retarget Pose From MeshのLOD
MannyのABPを流用して子のSkeletalMeshを動かせる機能「Retarget Pose From Mesh」について。 場合によっては子のSkeletalMeshのLODが動作しないことがある。(MetahumanはLODSyncがあれば大丈夫っぽい)
子のSkeletalMeshにて「Sync Attach Parent LOD」がONになっていると親(Manny)のLODが反映されてしまう? OFFにすることで子側のLODが動作。 「Retarget Pose From Mesh」を使っている人はコマンドラインの「show LODColoration 」でSkeletalMeshのLODが動作していることを確認した方が良い。
Retarget Pose From Meshは重い
「Retarget Pose From Mesh」でMannyなどのABPを流用する方法だけど、重くなる原因なのでなるべく控えた方が良い。
大量にキャラクターを出したいなどであれば後々ネックになってくるので注意
「Set Master Pose Component」でメッシュを全て指定しないといけないので、特にMetaHumanのようにLegsやらFeetやら多いとなおさら重くなる。 別の方法にて「Skeletal Mesh Merge」もあるためそちらも検討すること。
PostProcessAnimBPの無効化
MetaHumanがとんでもない重い原因の一つです。
BodyやFaceのPostProcessAnimBPを無効化することで改善する場合があります。
「MetaHumanによるデジタルヒューマンの実現と可能性」の資料が分かりやすかったです。
ControlRigで指に計算を無効化
LOD:0~2で指のひねりの計算をする。
LOD:3以降で指のひねりの計算のコストを抑える。
「MetaHumanによるデジタルヒューマンの実現と可能性」の資料が分かりやすかったです。
PostProcessAnimBPのLOD
スケルタルメッシュのPostProcessAnimBPのLODを設定する。
「MetaHumanによるデジタルヒューマンの実現と可能性」の資料が分かりやすかったです。
Material関連
Maskedはなるべく使わない
マテリアルはMaskedが重く、60FPSのゲームを目指すためにもなるべく不透明(Opaque)にすることが重要とのこと。 木などのアセットを見るとMasked Materialが使用され、自然な揺れ(WPO)が利用されているため重い原因となりやすいみたい。
重いMaterialを探す
シェーダーの複雑度から重いマテリアルの特定する。
重いマテリアルの特徴 ・半透明 ・描画の重なりが多い ・テクスチャの枚数が多いなど
アニメーション関連
Visiblity Based Anim Tick Option
SkeletalMeshの最適化項目にて
「Always Tick Pose and Refresh Bones(常にアニメーションの計算を行う)」
↓
「Only Tick Pose when Rendred(描画時のみ)」に設定。
ゲーム仕様によるため設定は注意。
「【UE4ゲーム制作】ゲームのパフォーマンスを向上させる方法【逆引きUE】」が参考になります。
Enable Update Rate Optimizations
SkeletalMeshの最適化項目にて「Enable Update Rate Optimizations(カメラの距離に応じてアニメーションをスキップさせる機能)」をONにする。 ちなみにその下の「Display Debug Update Rate Optimizations」にチェック入れるとデバッグ可能。
「【UE4ゲーム制作】ゲームのパフォーマンスを向上させる方法【逆引きUE】」が参考になります。
Use Attach Parent Bound
親子関係の子側の「Use Attach Parent Bound」をONにする。
「【UE4ゲーム制作】ゲームのパフォーマンスを向上させる方法【逆引きUE】」が参考になります。
その他
Nav Mesh Bounds Volume
「ナビメッシュバウンズボリューム」 の設定の際はなるべく薄く小さく最低限に設定する。画像例ではAIキャラが入らないような余計なビルごと範囲で囲ってしまっているため無駄がある。後は可能であれば細かく範囲指定するとか。
StatFPSとStatFPS
「Stat FPS」と「Stat Unit」をONにする。
ふと入れた処理が実は重かったり、テスト時に早期に発見できるので必ず起動を癖にしておく。 (Save Engine Stats (エンジン統計の保存)にチェックで毎回表示も可能)
Stat Unitでどこが重いか判断。
・Game(CPU) リアルタイムで動作するゲームのロジック、アニメーションの評価
・Draw(CPU) 描画関連
・RHIT(CPU) CPUとGPUを橋渡し
・GPU メッシュ、マテリアル、ライティング、ポストプロセス
Stat GPU
CPUがネックなのかGPUがネックなのか確認すること。
CPUが重いのにGPUを最適化しても速くはならない。
GPUが重いのにCPUを最適化しても速くはならない。
GPUが重さの原因であればStat GPUで確認。
ProfileGPU
コマンド「profilegpu」にてGPUビジュアライザーを確認。
重い個所を見つけて修正し、 30FPSであれば「33.33ms」、 60FPSであれば「16.66ms」に収める必要がある。
UE5.4を使おう
UE5.4では「レンダリングスレッド時間が50%削減され、GPU時間が25%削減」とのこと。UE5.0と比べてとのことなので、どこまで本当かは分からないが特にバージョンにこだわりがない人はUE5.4(最新のもの)を使おう。
固定FPS
これはゲームの開発環境や仕様に依存しそうだけど、固定フレームレートを使用することで自分のゲームは安定した。 スムージングの場合、自分の環境ではActorスポーン時にとんでもなくFPSが低下した。 固定にすることで少し安定した。
Unreal Insightsの確認
Unreal Insightsを確認することで負荷が上がっているであろう場所が確認可能。
クリックすることで、範囲と情報を表示してくれる。 負荷の意外な原因が分かったりするのでかなり重要。最適化ではこれが最強なので必須
アクタの再利用
場合によっては最強の最適化「アクタの再利用」
通常であればSpawnActorし、利用が終わればDestroyActorすると思います。 そのDestroyActorをせず、アクタの設定値などを全て初期値に戻し、スポーン位置にテレポートするなど
例)
①出現ポイントから敵がスポーン
②敵のHPが0になる(倒す)
③敵のVisibleをOFFにする(死亡したように見せる)
③出現ポイントに敵をテレポート(DestroyActorしない)
④敵のHPを100に戻す、VisibleをON
⇒まるで敵が新しくスポーンされたかのように見せる(再利用する)
ただし、処理が軽くなるかは場合によってなので注意。
・そもそもスポーン処理など重くなければ対応不要
・設定値を全て元に戻すなどバグの温床になりうる
・スポーン時(BeginPlay)に大量の設定や物理計算などある場合は効果あり?
⇒UnrealInsightsで確認して、実はスポーン処理がネックとかであれば
おまけ
Steamのストアページでは最低スペック・推奨スペックなどの記載個所がありますが、だいたいが各自が持っている検証機がその最低・推奨スペックになると思います。
ただ、可能であればその検証機より少し上のスペックを見積もっておいた方が良いと思います。
何故かというとゲーム実況・配信の方がゲームをする場合、ゲームの起動+録画・配信ソフトを起動するということが大半なのでかなり重くなる場合があります。
「最低スペックでの検証機では問題なかったが、録画ソフトも動いているので少し重い」などのことが起こりうる感じです。
デフォルトのゲーム画質設定を低めに調整しておいて、後はユーザ側で好きな設定にいじってもらいゲームを楽しんでもらうなど対策が必要になります。ただし基本的にはゲームの設定を変えないで遊ぶほうが大半だと思うので体験してもらいたいゲームのクオリティを提供できない可能性があります。(そこは難しいところかと・・・)
逆に録画・配信ソフトなどの環境をお持ちの開発者の方は、ゲームと両方を起動した状態で最終調整してみるのもありかと思います。
終わり!