世界を動かす技術を、日本語で。

未使用のツールチップを生成せずにUnreal Editorの起動を高速化する

2025年9月3日原文(larstofus.com)

概要

Unreal Engineは多機能だが、エディタ起動時間が長い問題がある。 ツールチップ生成がパフォーマンス低下の大きな要因。 全ツールチップを起動時に生成する現状から、必要時のみ生成に変更可能。 この最適化でメモリ使用量と起動時間が大幅に削減。 プロジェクト設定やエディタ設定パネルが主なツールチップ生成源。

Unreal Engineの起動パフォーマンス問題とツールチップ最適化

  • Unreal Engine は近年「ゲームエンジン」から 多目的編集ツール へと進化
  • ゲーム開発 だけでなく、映画・VFX・ライブ配信・バーチャルファッションショー等に活用
  • 機能が多いため、 エディタ起動時間が長い という欠点
  • Epicは Live-codingDerived Data Cache などで対策を実施
  • テスト用シンプルレベル を起動時に使う等の個別対策も存在
  • しかし、これらの対策は プロジェクト依存 かつ 手動作業 が必要

起動プロセスの分析

  • エディタ起動時のパフォーマンス を詳細に調査
  • 一見無害な ツールチップ用関数 がパフォーマンス低下の原因と判明
  • この関数は単にテキストを設定するだけでなく、 ウィジェット全体を生成
  • 全ツールチップ に対してこの処理を実行、無駄なリソース消費
  • Unreal Engine 5.6以前では ツールチップテキストだけで約1GB を消費
  • 簡単なトップダウンテンプレートプロジェクト でも 約38,000個 のツールチップ生成
  • 実際に1セッションで読むツールチップは 5~10個程度、大半が未使用
  • デバッグビルド ではツールチップ生成だけで 2~5秒 の遅延発生
  • 開発ビルド でも1秒未満だが、 約40MBのメモリ消費

最適化アプローチ

  • 全ツールチップ生成を起動時から実際の表示時に遅延
  • テキストを属性として保存し、 必要時のみウィジェット生成
  • これにより 未使用ツールチップのリソース消費を回避
  • 1フレームで生成されるツールチップは最大1つ、 パフォーマンス影響は無視できるレベル
  • ツールチップ生成は0.05ms 程度、体感で遅延なし

実装と影響

  • Pull Request を公開中(Unreal-Linked GitHubアカウント要ログイン)
  • Epic Gamesによるマージ を期待
  • プロジェクト設定パネルエディタ設定パネル が主なツールチップ生成源
  • これらのパネルをデフォルトで開かない・不要なパネルをレイアウトから外すことで、 起動速度向上が可能

ツールチップ生成最適化のまとめ

  • 必要なタイミングでのみツールチップ生成 という設計変更が効果的
  • 起動時間短縮メモリ使用量削減操作時の遅延なし を実現
  • 不要なパネルやツールの削除 も有効な最適化手法
  • Unreal Engineの 利便性とパフォーマンス向上 に寄与するアイディア

Hackerたちの意見

これを見て思い出したんだけど、Reactアプリをプロファイリングしたときにツールチップがかなりの割合を占めてたんだよね。ちょっと確認してみるべきだな。それと、こういうモーダルを追加するのも {isOpen && } みたいにすると、モデルが増えるほどアプリがスムーズになる気がする。必要なときだけUIをレンダリングするのは、パフォーマンスを最適化するための簡単な手段だと思う。

Blazorの世界では、モーダルやツールチップの新しいインスタンスを生成するためにファクトリーやマネージャーを使うんだ。何もせずに待機しているよりもね。複雑なコンポーネントの場合、初回のレンダリングが遅くなるというトレードオフがあるけど。

この問題を以前に解決したことを覚えてるよ。これらは両方ともグローバルコンポーネントだから、単一のグローバルインスタンスを作って、グローバルコンテキストや関数で制御するんだ。基本的には、コンポーネントのグローバル部分とローカル部分がある。グローバル部分は必要なときに実際にレンダリングされて、現在の状態を管理する。ローカル部分は特定のトリガーのためにグローバル部分内でレンダリングされる内容を定義して、トリガー条件が発生したときにグローバル部分とやり取りする(例えば、ツールチップのホバータイムアウトみたいに)。

それだとアウトトランジションが壊れちゃうね。

それとも、同時に開けるモーダルはどれくらい?それって浮遊する要素なの?必要なときにコンテンツを設定するグローバルなシングルインスタンスにする選択肢もあるかもね。別のコメントでも指摘されてたけど、入出力のトランジションもできるし。Reactの「ポータル」も参考にしてみて。

コード内のライブラリが数人のユーザーから全員に使われるようになると、その後は定期的に監査しなきゃいけないよね。私たちのコードのライブラリの一部は、何年もかけてレスポンスタイムが20%に達してた。数ヶ月でそれを半分に減らしたけど、アーキテクチャやキャッシュの変更はなし。チームで完了した中で、最大かつ最もコスト効率の良い取り組みだったと思う。フレームチャートを見るのは第一歩に過ぎない。呼び出し回数も確認する必要があるよ。思ったよりも頻繁に呼ばれているものがあるからね。プロファイリングツールは、CPUサブシステムの負荷によって関数のコストを誤って割り当てることがよくある。期待以上の大きな改善を見つけたときは、たいていは累積呼び出し回数から来てることが多いんだ。

無料の漏れのある抽象化について言ってみろって?そしたら、隣のスレッドでChromeプロファイラーを使ってChromeの内部をScratchで診断してるのを指摘するよ。それから、少なくともUnrealには本物の90年代の雰囲気があるって言って終わる。

これはIMGUIアプローチが偶然にでも小さな勝利を得るシナリオの一つだね。即時モードでGUI要素が必要に応じて構築されるから、見えない/未使用の要素にはツールチップのセットアップが実行されないし、ツールチップのセットアップコードはおそらくツールチップを表示しているコントロールのためだけに実行されるだろうね。(IMGUI APIによっては、すべての表示されているコントロールに定数としてツールチップテキストを事前に設定しているかもしれないけど、それでも38000のコントロールよりはかなり少ないと思う。)以前はすべてのコントロールが専用のツールチップコンポーネントを持っていたのが面白いね。なぜすべてのコントロールが単一のシステム全体のツールチップを共有しなかったのか、ちょっと気になる。

これってReactみたいなアプローチ(React、Flutter、SwiftUI)と比べるとどうなの?あのライブラリたちはIMGUIがやることをもっと構造的にやってる感じがする。

UnityはIMGUIアプローチを使ってて、それが宇宙の全てを変えるんだよね。OnDrawGizmosメソッドをオーバーライドして新しいコンポーネントのエディタービジュアルをすぐに表示させるのがすごく効率的。色を設定し忘れたりするようなちょっとした問題はあるけど、その便利さのためにこういう小さなストレスは全然気にならない。俺の知る限り、UEは保持モードのGUIに依存してるけど、そのバージョンのナルニアにはあまり深く入っていけなかったから、実際に体験したことはないんだよね。

なんでダウンボートされてるのか分からないけど、俺も同じこと考えてたよ。即時モードだとウィジェットやオブジェクトを構築する必要がないからね。毎フレームコードで描画するだけで、UI要素に対するアプローチが自由になるんだ。アプリ全体で一つのウィジェットシステムに縛られないから、例えばツールチップのコードが遅いと感じたら、メモリのブロック内の文字列をmemcpyして、ツールチップがそのメモリのインデックスを使うようにしたり、ディスクやクラウド、宇宙から必要に応じてロードさせたりできる。要するに、UIを部分的に最適化できるってこと。即時モードには独自の課題があるけど、異なるアプローチが問題にどう対処するかを見るのは面白いと思うよ。

コードを読むアクセスはないけど、理想的には起動時にインスタンスは一つだけ作成されるべきだよね?

Hacker Newsで議論の続きを見る