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

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

概要

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を部分的に最適化できるってこと。即時モードには独自の課題があるけど、異なるアプローチが問題にどう対処するかを見るのは面白いと思うよ。

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

起動時には最大で一つのインスタンスだけ。非同期作成や初回使用時の遅延作成も他の選択肢だね。一般的に言えば、Unreal特有の話ではないけど。

一度、Fabからサウンドエフェクトを買ったことがあって、そのせいでUnreal Engineを丸ごとダウンロードしてプロジェクトを作らないといけなかったんだ。アセットをインポートするためにね。午後全部かかっちゃったよ。UE5のゲームが最適化が悪いって評判なのも納得だよね。エディターを動かすだけでもすごいスペックのマシンが必要なんだから。最先端のグラフィックスパイプラインなのに、ソフトウェアの面ではウェブ開発レベルの無駄がある。Unreal EngineエディターよりもElectronの方がスムーズな体験だって言えるかも。

それでも、業界を支配していて、あらゆるアーティストに愛されているエンジンなんだよね。UEのゲームをちゃんと動かすには、自分たちでエンジンチームを持って最適化するか、すべての新しい機能を諦める必要がある。

コンピュータやIDEと同じで、一度立ち上げたら二度とシャットダウンしない感じだよね。午後全部かかるのは、アセットをダウンロードしてインストールしたり、キャッシュを作ったり、インデックスを作ったりしてるからじゃない?IDEと同じで、一度立ち上がっちゃえばあまり気にしなくなるし、最終的に製品のパフォーマンスは使うツールとはあまり関係ないんだよね。最適化が悪いゲームはそういう評判があるけど、それはエンジンのせいじゃないことが多い。もしかしたら、使いやすくてネットからアセットをポンと置くだけでパフォーマンスやシーンごとのパフォーマンス予算を調整しないのが問題なのかも。

UE5のゲームが最適化が悪いって評判なのは納得だね。具体例を挙げてくれる?俺はUEのゲームが最も最適化されてると思うし、どこでも動くと思ってるよ。例えば、X-COMは14年前のLinuxノートパソコンでi915のグラフィックカードでプレイできるけど、Unityのゲームはここでは動かないし、WindowsのゲーミングPCではすぐに熱くなっちゃう。UEのゲームのクオリティや忠実度には全然及ばない。俺にとってUEはSolidWorksみたいで、UnityはFreeCADみたいだな…まぁ、実際にその違いに近いと思うけどね :-) それとも「最適化が悪い」という評判はUE5特有のものなのかな?(古いUEバージョンと比べて)

初めてシェーダーをコンパイルするのに時間がかかったから、そんなに長くかかったんだよね。その後は数秒で開くようになるけど。

うーん、その1GBのツールチップには何が入ってるの?言語ごとに10万個のツールチップがあっても、せいぜい数十メガバイトのスペースを取るはずだよね。エディターにはどれくらいのローカライズがあるの?

テキストデータじゃないんだよね。すべてのツールチップがUI要素にされちゃうから。「まず、名前とは裏腹に、この関数はツールチップのテキストを設定するだけじゃなくて、テキストを表示するためのサブウィジェットやヘルパーオブジェクトを含むフルツールチップウィジェットを生成するんだ。パフォーマンスの観点からは理想的じゃないよね。他の問題は?Unrealはエディター全体のすべてのツールチップにこれをやってて、Unrealにはたくさんのツールチップがあるんだ。実際、バージョン5.6までのすべてのツールチップのテキストだけで約1GBのストレージを占めてた。」でも、1GBのストレージにはボイラープレートも含まれてると思う。生のテキストが1GBもあるとは思えないな。

純粋に技術的な観点から見ると、UEは絶対的なモンスターだよ。UnityやGodotとは全然レベルが違う。イテレーションの難しさやツールの使いやすさでね。HDRP相当やナノメートルメッシュ解像度が必要じゃないプロジェクトだと、他のエンジンよりUEが苦手なんだ。Unityも楽勝ってわけじゃないけど、AAAの魔法使いみたいな全軍を持ってない限り、イテレーションのスピードはかなり高いよ。UEのプロジェクトをやってると、幸せな道にいる感じが一度もなかった。GodotやUnityは比較するとズルしてるみたい。~インスタントプレイモードや簡単なデバッグ体験は、ソロや小規模チームには大きな違いをもたらす。経験豊富な.NET開発者なら、合理的なメンターがいれば1日以内にUnityプロジェクトで生産的になれるよ。UEでのベストな戦略はブループリントを使うことだったけど、ソース管理やコードレビューの時間には本当に悪い。

俺の経験では、ブループリントを繋ぐのに時間がかかりすぎる。C++を直接書く方がずっと早いよ。

新しいクエスト: 「これらの新しいゲーム要件は非現実的」 目標: HDRPとナノメトリックメッシュを要求するプロジェクト ボーナス: ハッピーパスを見つける

HazelightのAngelScript UEフォークを試すまでは、俺も全く同じ気持ちだった。すごく良くて、開発者体験と反復速度がUnityレベルに達してる。VSCodeのプラグインまで作ってくれたし、めちゃくちゃおすすめだよ。

UEはグラフィックがめちゃくちゃいいから、ほとんどの開発者が使う理由がないと思う。なんで多くのインディー開発者がこれを選ぶのか、全然理解できない。

ブループリントはすごくいい学習ツールになり得るよ。ノードをダブルクリックすると、実際のC++コードの関数が表示されるVSウィンドウが開くから。

Unityが企業顧客からぼったくりみたいなことになってるのに対して、Godotはまだ競争するには成熟してないって考えると、ほんとに残念だね。ゲームエンジンがどんどん問題になってきてる。

Unrealに関しての俺の問題は、Epicが開発者体験の改善にあまり力を入れてないことだね。技術デモや派手なビジュアル、半端な機能を出すことに集中してて、実際に使えるようになるのは何回もメジャーリリースを経てから(もしそうなら)。うちのアーティストたちは好きだけど、開発者はあんまり好きじゃない。

UnrealとUnityを組み合わせてフルタイムで5年間働いてきた。Frostbiteでも5年間、いろんなカスタムエンジンでも5年間働いたことがある。UnrealもUnityも大好きだよ。技術的な観点から見るとUnrealは素晴らしいし、才能あるチームと一緒に作業したことで、持っていたリソースを考えると驚くべきものが作れた。Unityは高い忠実度のグラフィックにこだわらなければ、ずっと扱いやすい。実際、Unityほど扱いやすいエンジンには出会ったことがない。モンスターだなんて絶対に呼ばないよ。比較的経験の浅いチームでも、すぐに作業に取り掛かれて、Unityでかなり生産的になれるんだから。

Cryengineってまだ使われてるの?それに、今の世代のidソフトウェアのエンジンでゲームがもっと出てこないのも不思議だよね。

元々は「38000個のツールチップを生成しないことでUnreal Editorの起動を速くする」というタイトルで投稿されていたんだけど、実際の投稿タイトル「...38000個のツールチップを生成しないことでUnreal Editorの起動を速くする」に近いよね。なんで変更されたの?ツールチップの数がタイトルを良くしてるし、投稿内容にも合ってると思うんだけど。

エディター全体を作り直すか、少なくとも使ってないシステムを削除する必要があるね… あんなに大きいのは許せないよ。

最近、Unrealを使う最速の方法は捨てて他のものに切り替えることだと決めたよ。空のプロジェクトをコンパイルするのに10分もかかるんだから。Godotが好きなのは主にGDScriptのおかげで、何もコンパイルしないから反復作業の時間が大幅に短縮されるんだ。Unigineも触れておく価値があるね。倍精度やグローバルイルミネーションなど、欲しい現代的な機能がすべて揃ってるけど、無駄や複雑さがない。エンジンを必要なだけ使うのが簡単で、どのプロジェクトでもmain()関数を書くことになる。UnityやUnrealと似たライセンスオプションもあるよ。