こんにちは、ISID 金融ソリューション事業部の岡崎です。
ゲームや動画などを作成する際に、ユーザーが違和感なくコンテンツを使用するためには、
フレームごとの描画速度(フレームレート)を意識し、パフォーマンスを担保し続ける必要があります。
今回はUE5でパフォーマンスを担保するために必要な、プロファイリングのワークフローの説明を行います。
はじめに
UEでは、制作したプロジェクトの性能を測るためにプロファイリングという作業を行います。
プロファイリングは、主にパフォーマンス改善を目的として実施します。例えばコマンドや専用のアプリケーションを使用して、描画に遅延が起こっていないか、不要な処理をしているBlueprintがないか、などを調べます。
今回の記事では、UEの基礎的なプロファイリングの方法(GPU編)について紹介していきます。
CPUに関しては記事が長くなるので、次の記事でご紹介します。
検証環境/ツール
- OS:Windows 11 pro
- GPU:NVIDIA GeForce RTX 4070 Ti
- Game Engine:Unreal Engine 5.2.0
実装手順
- 「stat unit」コマンドの実施
- Drawsが多い場合の対処方法
2-1. 対象メッシュの確認、削除
2-2. Naniteの設定(UE5の場合)
1. 「stat unit」コマンドの実施
まず初めに、「stat unit」コマンドについて説明していきます。
UEではさまざまな方法でプロジェクトのプロファイリングを行う方法があります。
「stat unit」はプロジェクト全体を俯瞰し、大体どの辺に致命的なバグや遅延の原因があるかなどを調べるのに適したコマンドになります。
「stat unit」コマンドを使用するためには、デバッグしたいプロジェクトを開き、画面下部よりアウトプットタブを押下し、
コマンド入力スペースに「stat unit」を記述します。
画面上に画像のようなログが出てきます。
主要な項目の説明をします。
- Frame : 画面を描画するのにかかった処理時間。60FPSのゲームを作成する場合は、16.6ms以下になるように調整しないといけない
- Game : リアルタイムで動作するゲームのロジックやアニメーションにかかるCPUの処理時間
- Draw : 何を描画するか、選択や計算をするためにかかるCPUの処理時間
- GPU Time : メッシュや各マテリアルの描画や、ライティングなどにかかるGPUの処理時間
- Draws : 描画する必要のあるメッシュの個数。GPU Timeに影響を与える
またGameなどの数値は、ゲームをプレイしている最中にBlueprintなどに連動して数値が変動するので、
ゲームをプレイしてキャラクターの操作などを行った際の数値も確かめる必要があります。
今回はGPU編なので、「stat unit」の結果から、
「Draw」、「Draws」の数値を調査、修正を行っていきます。
その他の項目のCPUに関わる箇所は次の記事で紹介するので、本記事では割愛します。
2. Drawsが多い場合の対処方法
Drawsの数値が大きい場合は、メッシュが大量に配置されていたり、ポリゴン数の多すぎる複雑なメッシュが配置されてしまっている可能性があります。
今回は、16.6msを超えているため、正常時は緑に表示される数字が赤文字になっています。
この Drawsの数値が大きいように感じたので調査していきます。
まずはレベル上にどのようなメッシュやポリゴンがあるか確認していきます。
2-1. 対象メッシュの確認、削除
画面上部のツールから、オーディット>統計 を選びます。
すると別画面でレベル内に配置されているメッシュのポリゴン数を確認することが出来ます。
「Tris」と書かれている部分がポリゴン数で、「Sum Tris」と書かれている部分が合計のポリゴン数になります。
今回の統計では、「SM_Movehuman」というオブジェクトの「Count」が「31,834」になっており、「Sum Tris」の数値も非常に高くなっています。
一般的にポリゴン数は下記の閾値を参考にすると良いとされています。
- 2000から3000までが理想
- 5000を超えると重たくなり始める
- 10000を超えると問題が起こり始める
このためDrawの数値が大きくなっていることが考えられます。
プロジェクトに戻って確認してみると、
実はこのレベルには大量の「SM_Movehuman」のアクターを配置していたことがわかりました。
もちろんこのプロジェクトは処理を重くすることを目的に作成しているので簡単に発見できましたが、
実際のプロジェクトでは、ここまで単純に問題を発見することはなかなか出来ません。
しかし、統計を見ながらレベルに配置してあるオブジェクトの個数や、ポリゴン数を確認し、大体のあたりをつけるのにはとても有効な手段です。
今回のように、オブジェクトが大量にあり「Draws」の数値が非常に高い場合の対処法は大きく3つあります。
- 無駄なオブジェクトの削除
- UE5で追加された「Nanite」を使用
- オクルージョンカリングの設定
※オクルージョンカリングの設定方法は本記事では説明しません。次回以降の記事で紹介する予定です。
まずは無駄なオブジェクトの削除を試します。
本プロジェクトでは、「SM_Movehuman」のアクターをすべて削除してみます。
「stat unit」の値を確認してみます。
「Draws」の値が下がり、「Draw」にかかる処理速度も短くなっていることが確認できます。
アクター削除前
アクター削除後
また、本プロジェクトでは割愛しますが、統計内の「Count」の数を下げなくとも、そもそものポリゴン数を少ないものを用意するのも有効です。
もし配置してあるオブジェクトが全て必要なもので、削除できない場合は次の手段を試します。
2-2. Naniteの設定(UE5の場合)
Naniteとは
まずNaniteを簡単に説明をします。
Naniteとは、UE5から搭載された、3Dモデルを効率的にかつ高速にレンダリングしてくれるシステムで、LODを自動で行ってくれます。
LODというのは Level of Detail の略で、ひとつのオブジェクトに対し、複数の粗さの違うメッシュを作成し、
カメラが遠くにあるときには粗く軽いメッシュを使用し、近くにあるときは細かく正確なメッシュを使用する描画方法です。
これによりユーザーに違和感やメッシュの粗さを感じさせずに、描画速度を上げることができます。
Naniteが搭載される前は、これらの複数のメッシュを用意し、距離を計算し配置する作業は手作業で行っていましたが、
LODがNaniteによって自動化され、手作業でやるよりさらに効率的にレンダリングできるようになりました。
Naniteの設定方法
Naniteはスタティックメッシュにのみ使用できます。(スケルタルメッシュなどには設定できないので注意が必要)
設定したいスタティックメッシュを開きます。
今回はレベル内に配置してある大量の人型のオブジェクトに対し、Naniteの設定を行っていきます。
スタティックメッシュを開いたら詳細パネルより、Naniteの設定 > Naniteサポートの有効化 をオンにします。
スタティックメッシュを保存し、レベルに配置するためのアクタークラスBlueprintを作成します。
コンポーネント内にスタティックメッシュを追加し、詳細画面から先ほどNaniteの設定をしたスタティックメッシュを選択します。
あとは、このアクターをレベル上に配置して負荷に変化があるか検証していきます。
Naniteによる負荷軽減の検証
PCGを利用して人型のアクターを大量に配置したレベルを用意し、Naniteを設定したものと、していないものでどれだけ数値に差が出るか調査しました。
それぞれのゲーム上で「stat unit」を行います。
(今回の記事ではPCGに関しての説明は割愛いたします。)
Naniteを有効にしていない場合
Naniteを有効にしている場合
Drawsの数値が劇的に減少され( 18143 → 559 )、Frameにかかる時間も16ms ほど短縮できています。
今回はデフォルトで用意されている人型のメッシュに対しNaniteの設定を行いましたが、
ZBrushなどで作成した複雑でポリゴン数の多いオブジェクトなどに対してNaniteの設定を行うことで、劇的に描画速度を向上できます。
おわりに
今回は、UE5を利用してプロファイリングの方法のGPU部分に関して、
ボトルネックになっている箇所を探し、対策する方法などをまとめました。
今回は検証用に作成したプロジェクトだったため、単純明快に問題の発見と解決ができましたが、
実際のプロジェクトでは、より複雑に原因が入り組んでいることが想像できます。
実践を積みながら、プロファイリングについてもっと詳しくなっていきたいです。
本プロジェクトでは、まだCPU側にボトルネックがありFrameの数値が140msと、非常に遅くなっているので、
次の記事ではCPUに関するプロファイルング方法をご紹介していきます。
現在ISIDはweb3領域のグループ横断組織を立ち上げ、Web3およびメタバース領域のR&Dを行っております(カテゴリー「3DCG」の記事はこちら)。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください!
私たちと同じチームで働いてくれる仲間を、是非お待ちしております!
ISID採用ページ(Web3/メタバース/AI)
執筆:@okazaki.wataru、レビュー:@kano.nanami
(Shodoで執筆されました)