リアルタイム シミュレーションやゲームでは、レンダリングやゲームプレイのために CPU、GPU、テクスチャ メモリにかかるコストがユーザー インターフェース (UI) と比較して格段に大きいです。そのため、一般的に UI は他のシステムよりもパフォーマンス バジェットの割り当てが少なくなっており、こうしたバジェット制約はリソースが限られているデバイスにおいて最もよく感じられます。そのため、限られたリソースをできるだけ効率的に使用し、UI でのリソース消費を可能な限り抑えることが重要になります。
UI のニーズは、プロジェクトの詳細とターゲット プラットフォームに依存しますが、Unreal Engine の スレート と UMG を使用して UI を構築する際に従うことができる最適化のガイドラインがいくつか存在します。このページでは、これらのベスト プラクティスの概要についてご紹介します。
- パフォーマンスの足跡を減らすことができる最適化機能。
- 最も CPU 負荷の高いウィジェットに関するガイドライン。
- UMG レイアウトを構築する際に避けるべき事項についての情報。
- UMG における様々なアニメーション手法の CPU コストの概要を説明します。
最適化およびプロファイリングに関する一般的な情報は、以下のページを参照してください。
無効化
無効化スレート ウィジェットの情報をキャッシュし、ペイント、レイアウト、階層情報が無効になるような変更がないか監視しています。ウィジェットが変更されない限り、スレートはウィジェットを再描画する代わりに、キャッシュされた情報を使用します。変更によってこの情報が無効になると、スレートは情報を再計算し、ウィジェットを再描画します。
Unreal Engine は、UI に無効化を組み込むためのいくつかの方法をサポートしています。
- 無効化ボックスは、その子ウィジェットの情報をキャッシュします。
- グローバルな無効化は、
SWindow
全体を無効化ボックスとして扱い、UI 全体に無効化を適用します。 - Retainer Panel は、子ウィジェットを単一のテクスチャにフラット化してからペイントし、フレームレートの設定やレンダリングを遅延させるオプションを提供します。
無効化は、頻繁に変更されないウィジェット群に対して最も効果的であり、フレームごとにメモリを犠牲にして再描画していた CPU 負荷を効果的に解放することができます。フレームごとに変化するウィジェットは、Volatile とマークして、情報を不必要にキャッシュしないようにします (いずれにせよ、フレームごとに再描画されるからです)。
これらのシステムの詳細、実装方法の詳細、制限については、「スレートと UGM での無効化」を参照してください。
プログラミングとスクリプト処理
UMG の環境下でプログラミングを行う際のベスト プラクティスは以下の通りです。
On-Tick または On-Paint ロジックを控えめに使用する。
UI でロジックを実行する場合、On Tick や On Paint の使用は可能な限り避けなければなりません。イベント・ディスパッチャとデリゲートを使えば、Tick に依存することなく、特定のイベントに反応するロジックを作成することができます。
バウンド属性の代わりにイベント駆動型アップデートを使用する
UI で属性をフィールドにバインドすると、フレームごとに属性をポーリングします。例えば、テキストフィールドのテキスト値を整数にバインドすると、そのプログレス バーはティックごとに整数の値をそのフィールドに代入することになります。これは非効率的なので、バウンド属性の使用は避けるべきでしょう。

Raw 属性のバインディングは絶対に使用しないでください。
その代わり、これらのフィールドを更新するために、UI で関数やイベントを呼び出すようにプロジェクトを設定する必要があります。例えば、ヘルス値バーを Health 属性にバインドする代わりに、UI のブループリント・スクリプトで OnHealthChanged
イベントを呼び出し、UI の必要なフィールドを変更する必要があります。

イベントを使って UI を更新する例です。
この設定の方が時間がかかりますが、それぞれのフレームではなく、値が変化したフレームでのみ UI が変化することが保証されます。
読み込みと構築
ウィジェットを構造化し、実行時にビルドするためのベスト プラクティスを以下に示します。
未使用のウィジェットをできる限り減らす
ウィジェット内のすべての子ウィジェットは、表示されているかどうかに関係なく、読み込まれて構築されます。UI でレンダリングしない場合でも、メモリを使用し、読み込みや構築の時間が必要になります。
基本的なことですが、UI デザイナーは定期的に未使用のウィジェットをチェックし、作業のコミット前に削除しておく必要があります。定期的に点検削除をすると、パフォーマンスだけでなく、整理整頓にも役立ちます。
ランタイムに読み込むことができるように複雑なウィジェットを分割する
主要なシステム用ウィジェットで、特に複雑なものになると、そのすべての機能を処理するために 1000 以上の子ウィジェットを持つことができますが、一度に表示する必要があるウィジェットは数百のみになります。このような状況で、ウィジェット全体を大きな塊として読み込むと、使われることのない何百もの非アクティブな子ウィジェットがスペースを占有する結果となります。子ウィジェットの専門性によっては、ユーザーは長時間それらを見ることはありません。
このような場合、ウィジェットをカテゴリに分ける必要があります。
-
常に表示されるウィジェット。
-
できるだけ早く表示させる必要のあるウィジェット。
-
表示時に多少の遅延を許容できるウィジェット。
高速なレスポンスが必要なウィジェットは、表示されていないときでもバックグラウンドで読み込まれるようにする必要があります。例えば、対戦型シューティング ゲームのインベントリ画面は、プレイヤーにとって重要な機能であるため、使用頻度も高く、高い応答性が求められるため、ロードして非表示にしておくことはグッドプラクティスです。
長時間存在することなく、高速なレスポンスが必要ではないウィジェットは、実行時に非同期でロードし、終了時に破棄する必要があります。多様な機能を持つ複雑なウィジェットでは、ベースとなるウィジェットを常にロードし、必要なモードや機能に応じて、異なる子ウィジェットのセットを非同期にロードする必要があるかもしれません。こうすることで、メモリを大幅に節約し、初期化時の CPU への影響を軽減することができます。
レイアウトと配置
UI のレイアウトを構築する際に、ウィジェットの効率性を高めるためのガイドラインを以下に示します。
キャンバス パネルを控え目に使用する
キャンバス パネル は、座標平面とウィジェットごとのアンカーを使用して他のウィジェットを配置することができる強力なコンテナ ウィジェットです。ウィジェットを思い通りに配置することも、画面の角や端、中心に対してウィジェットの位置を維持することも簡単に行うことができます。
しかし、キャンバス パネルには高いパフォーマンスが要求されます。スレートの描画コールは、ウィジェットの Layer ID でグループ化されています。Vertical Box や Horizontal Box などのコンテナ ウィジェットは、子ウィジェットのレイヤー ID を統合し、描画の回数を減らすことができます。ただし、キャンバス パネルは子ウィジェットの ID をインクリメントするので、必要であれば重ねてレンダリングすることができます。結果、キャンバス パネルは複数の描画コールを使用することになり、他の製品と比較して CPU への負荷が高くなります。
オーバーレイ パネルもレイヤー ID をインクリメントするため、複数の描画コールを使用します。キャンバス パネルと比較すると、使用される範囲が限定されるため、キャンバス パネルほどの影響はありませんが、オーバーレイを使用する際にも、この点に留意してください。
詳細な配置や複雑な Z 軸の順序付けが必要になる場合があるので、1 つのキャンバス パネルを使用して HUD やメニュー システムのルート ウィジェットをレイアウトすることは問題ではありません。ただし、テキストボックス、カスタムボタン、その他のテンプレート化された要素など、個々のカスタム ウィジェットをレイアウトするためにそれらを使用することは避けてください。UI の多くの要素でキャンバス パネルが何層にもネストすることになり、非常に多くのリソースを消費する結果になります。また、複数のレイヤーでキャンバス パネルを過度に使用すると、最終的にレイアウトの一部を決定する UI が分からなくなることがあります。
経験上、ウィジェットが単一の要素で構成されている場合、キャンバス パネルはまったく必要ありません。フルメニューや HUD の場合でも、オーバーレイ や サイズボックス、水平方向、垂直方向、グリッドボックス を使用してレイアウトを処理すれば、キャンバス パネルを完全に使用せずに済むことがよくあります。
サイズ ボックスの代わりにスペーサーを使用する。
サイズ ボックスは、サイズを計算し、それ自体をレンダリングするために複数のパスを使用します。もし、コンテンツが幅と高さで一定の大きさを占める必要がある場合、スペーサー はかなり負荷が低いです。
スケール ボックスとサイズ ボックスの組み合わせを避ける
スケール ボックス とサイズ ボックスの組み合わせると、互いに更新し合おうとして、フレームごとに 2 つのサイズを反転させるループにはまり込んでしまいます。これらのいずれかに頼らずに、コンテンツのネイティブ サイズに合わせたレイアウトを心がけてください。
リッチ テキスト ウィジェットは控えめにする
リッチ テキスト ウィジェット テキストに強力なフォーマットを提供しますが、さまざまな追加機能があるため、標準のテキスト ボックスと比べると非常に負荷が高いです。テキストにスタイルや表現力を持たせたいが、リッチ テキストの全機能を必要としない場合、デフォルトで必要なスタイル感を反映したフォントを選択または作成し、標準のテキスト ウィジェットにフォールバックする必要があります。
アニメーションのコスト
実行時にウィジェットをアニメーション化させるアプローチはいくつかあります。無効化で作業する場合、これらのメソッドのいくつかは、ウィジェットのレイアウトを無効化し、階層の分岐全体を再更新する原因となることがあります。次の表は、これらのアニメーション方式と UMG における相対的な CPU コストの一覧です。
コスト | 例 |
---|---|
No CPU Cost/Least Expensive | マテリアルのみのアニメーション。 |
Low CPU Cost | シーケンサーを必要としないブループリント・スクリプトのアニメーション。 |
High CPU Cost | UMGのアニメエディターで作成したシーケンサー アニメーション。 |
Most Expensive CPU Cost | レイアウト変更を引き起こすアニメーション。 |
マテリアルのみのアニメーションは GPU で処理されるため、CPU コストは発生しません。グロー効果、スクロールする背景、またはマテリアルの変更で表現できるその他の効果などのループするアニメーションには、この方法が望ましいです。アニメーションをマテリアルに含めることが可能であれば、他のすべての方法よりもこの方法を優先するべきです。
UMG のアニメーション・エディタはシーケンサーに実装されています。色などの非変換属性を変更するシーケンサー アニメーションは、ウィジェットを再描画する必要がありますが、レイアウトを無効にすることはありません。レンダリング トランスフォームを変更するアニメーションでは、レイアウトが無効になり、アニメーションがウィジェットを変更するフレームごとにレイアウトが再計算されます。これを避けるか、この種のアニメーションを必要とするウィジェットを Volatile (揮発性) としてマークする必要があります。
ブループリント スクリプトによるアニメーションとシーケンサー アニメーションはほぼ同等のランニング コストですが、シーケンサー アニメーションはアニメーションを開始する前にアニメーション オブジェクトを初期化し、そのアニメーションが担当するプロパティ パスを解決する必要があります。つまり、シーケンサー アニメーションには、Blueprint スクリプトによるアニメーションにはないスタートアップ コストが発生するのです。したがって、アニメーション化されたダメージ番号のような、短くて頻繁に使用されるアニメーションを扱う場合は、シーケンサーの使用を避け、代わりにブループリントで記述されたトゥイーンに依存することをお勧めします。