UMGの二大課題
Unreal Engine (UE) でユーザーインターフェース (UI) を構築する際、UMG (Unreal Motion Graphics) は非常に強力なツールです。しかし、プロジェクトが大規模になるにつれて、多くの開発者が二つの大きな壁に直面します。
一つはパフォーマンスの低下 です。「UIを開いた途端にフレームレートが落ちる」「画面に何も変化がないのにCPU負荷が高い」といった問題は、UMGの描画サイクルを正しく理解していないことが原因で発生します。
もう一つはフォーカス管理の難しさ です。特にゲームパッドやキーボード操作に対応する際、「メニューのカーソルが意図しない場所に飛ぶ」「フォーカスがどこにも当たらない」といった、プレイヤーの操作感を損なう問題が頻発します。
本記事では、これらのUMGにおける「よくある問題」を解決するため、初心者から中級者の方を対象に、フォーカス管理のベストプラクティス とパフォーマンス最適化の具体的な手法 を、豊富なBlueprintの例を交えて徹底的に解説します。
フォーカス管理
UMGにおける「フォーカス」とは、現在どのウィジェットが入力(ボタン押下など)を受け付ける状態にあるかを示す概念です。マウス操作が主体のPCゲームでは意識しなくても問題ありませんが、コンソールゲームやPCゲームのゲームパッド操作では、このフォーカス管理がプレイヤー体験の質を決定づけます。
よくある問題:フォーカスが迷子になる
デフォルト設定のままウィジェットを配置すると、UMGは自動的にフォーカス移動を試みます。しかし、複雑なレイアウトや非表示のウィジェットが存在する場合、この自動ナビゲーションが意図しない挙動を引き起こし、「フォーカスが画面外に飛ぶ」「隣のボタンではなく遠くのボタンに飛ぶ」といった現象が発生します。
解決策:ウィジェットのナビゲーション設定を明示する
この問題を解決する鍵は、各ウィジェットの 「Navigation」 設定を適切に利用することです。
-
初期フォーカスの設定 UIが表示された際、プレイヤーが最初に操作するウィジェットにフォーカスを当てる必要があります。
⚠️ 重要:Set User Focusのタイミング
Set User Focusは、ウィジェットがViewportに追加された後 でなければ正しく動作しません。Event Construct内で呼び出すと、ウィジェットがまだViewportに存在しないため、フォーカスが設定されない場合があります。Add to Viewportの後、またはEvent On Added to Focus Path内で呼び出すことを推奨します。Blueprint例:メニュー表示時に特定のボタンにフォーカスを設定
// UIを表示するBlueprintコード内(プレイヤーコントローラーなど) Create Widget (WBP_MainMenu) -> Add to Viewport -> Set User Focus (Target: MyStartButton, Player Controller: Self) -
明示的なナビゲーションの定義 ウィジェットの詳細パネルにある「Navigation」セクションを開きます。ここで、上下左右の移動に対して、どのウィジェットにフォーカスを移すかを明示的に指定できます。
設定モード 説明 ベストプラクティス Automatic UMGが自動で最適な移動先を推測する(デフォルト)。複雑なUIでは予期せぬ挙動の原因になりやすい。 シンプルなUIでのみ使用。 Explicit 上下左右の移動先ウィジェットを開発者が手動で指定する。 複雑なUIや、特定の移動順序を保証したい場合に推奨。 Custom 特定の方向の移動をカスタムロジック(Blueprint関数)で処理する。 特殊な移動ロジック(例:グリッド状の移動)が必要な場合に利用。 Stop その方向へのフォーカス移動を停止する。 画面の端や、特定のウィジェットから外に出たくない場合に利用。 ベストプラクティス: 複雑なメニューでは、すべての操作可能なウィジェットに対してExplicit 設定を使用し、移動先を一つ一つ指定することで、予測可能で安定した操作感を実現します。
UMGのパフォーマ ンス最適化
UMGのパフォーマンス問題の根源は、ウィジェットの再構築(Reconstruct)と再描画(Repaint) が頻繁に発生することにあります。UMGは内部的にSlateというUIフレームワークを使用しており、ウィジェットのプロパティが変更されると、そのウィジェットとその子ウィジェットの描画を更新する必要があります。
避けるべき間違い:On-TickとOn-Paintへの重い処理の記述
最もパフォーマンスを低下させる原因の一つが、ウィジェットブループリントのEvent Tickや、オーバーライドしたOn Paint関数に、毎フレーム実行される重いロジックを記述することです。
- On-Tick: 毎フレーム実行されます。ここで複雑な計算や頻繁なデータアクセスを行うと、CPU負荷が跳ね上がります。
- On-Paint: 描画が必要なときに実行されます。特にカスタム描画ロジックをここに記述する場合、描画コストが非常に高くなる可能性があります。
ベストプラクティス:
- データ更新は、データが実際に変更されたとき にのみ実行されるようにイベント駆動型で設計します。
- アニメーションや進行状況バーなど、毎フレーム更新が必要な要素は、可能な限りUMGのAnimationシステム やBinding を利用し、ロジックを最小限に抑えます。
Invalidation Box(無効化ボックス)
Invalidation Box は、UMGのパフォーマンス最適化における最も重要なウィジェットの一つです。
仕組み
Invalidation Boxは、その子ウィジェットの描画結果をキャッシュ(メモリに保存)しま す。子ウィジェットのプロパティが変更されない限り、UMGは毎フレームその部分を再描画せず、キャッシュされた画像を表示します。これにより、複雑なウィジェット階層全体の描画コストを大幅に削減できます。
使い方と注意点
- 配置: 頻繁に更新されない、複雑なウィジェットの親として配置します。
- 自動無効化: 子ウィジェットのプロパティが変更されると自動的にキャッシュが無効化 され、次回の描画で更新されます。
💡 手動Invalidateが必要なケース
通常はプロパティ変更で自動的に無効化されますが、C++から直接Slateを操作する場合や、バインディングを使わずにウィジェットの内部状態を変更する場合など、自動検出が効かないケースでは
Invalidateノードを手動で呼び出す必要があります。
Blueprint例:スコア表示ウィジェットの最適化
スコア表示ウィジェット(WBP_ScoreDisplay)が、ゲーム開始後ほとんど更新されないとします。
// WBP_ScoreDisplay の親ウィジェットのブループリント内
// スコアが更新されたイベントを受け取ったときのみ実行
Event OnScoreUpdated
-> Is Valid (Target: MyInvalidationBox)
-> Invalidate (Target: MyInvalidationBox)
よくある間違い:
- 頻繁なInvalidate: 毎フレームまたは数フレームごとに
Invalidateを呼び出すと、キャッシュのメリットが失われ、むしろオーバーヘッドが増加します。 - 単純なウィジェットへの適用: テキスト一つだけの ウィジェットに適用しても効果は薄く、複雑なレイアウトや多数のウィジェットを含む部分に適用することで最大の効果が得られます。
Retainer Box(リテイナーボックス)
Retainer Box は、Invalidation Boxよりもさらに高度な最適化と描画制御を提供します。
仕組み
- レンダーターゲットへの描画: Retainer Boxは、その子ウィジェットをレンダーターゲット(テクスチャ)に一度描画 し、以降はそのテクスチャを表示します。これにより、複雑なウィジェット階層を毎フレーム再描画するコストを大幅に削減できます。
- ポストプロセス効果: Retainer Boxは、子ウィジェット全体に対してマテリアル(ポストプロセス)を適用できるため、UIにぼかしや特殊なエフェクトをかける際にも利用されます。
💡 Invalidation Boxとの違い
Invalidation BoxがSlateレベルでの描画キャッシュ(無効化されるまで再計算をスキップ)であるのに対し、Retainer BoxはGPUテクスチャとして結果を保存 します。Retainer Boxはメモリ消費が大きい代わりに、より強力な最適化と描画効果の適用が可能です。
使い方と注意点
- パフォーマンス向上: 非常に複雑でドローコールが多いUI要素(例:多数の半透明な要素が重なり合うUI)に対して特に有効です。
- ポストプロセス:
Effect Materialプロパティにカスタムマテリアルを設定することで、UI全体にシェーダー効果を適用できます。 - Tick Rate:
Tick Rateを設定することで、Retainer Box内の描画 更新頻度をフレームレートとは独立して制御できます(例:30FPSで描画)。
ベストプラクティス: Retainer Boxは強力ですが、メモリ消費や初期設定のオーバーヘッドも大きいため、Invalidation Boxで解決できない、またはポストプロセスが必要な場合にのみ 使用を検討してください。
UMG最適化のチェックリスト
UMGのパフォーマンスと操作性を両立させるには、以下のポイントを常に意識してUIを構築しましょう。
- フォーカス管理:
- 初期フォーカスを必ず
Set User Focusで設定する。 - 複雑なUIでは
Navigation設定をExplicitまたはCustomで明示的に定義する。
- 初期フォーカスを必ず
- パフォーマンス最適化:
Event TickやOn Paintに重いロジックを記述しない。データ変更時のみ更新するイベント駆動 を徹底する。- 内容が静的な複雑なウィジェットにはInvalidation Box を適用し、描画をキャッシュする。
- Invalidation Boxで解決できない、または特殊な描画効果が必要な場合にのみRetainer Box を検討する。
これらのテクニックを適用することで、あなたのUnreal EngineプロジェクトのUIは、より快適で、よりプロフェッショナルな品質へと進化するでしょう。