【Unreal Engine】Unreal Insightsで重さの正体を掴む:statコマンドの次の一手

作成: 2026-07-25

stat unitでGameが重いと分かっても、どの処理が重いかは分かりません。Unreal Insightsでトレースを記録し、Timing Insightsでフレームを開き、呼び出しの入れ子をたどって自分のBlueprintを見つけるまでを図解。statで当たりを付けてInsightsで確定させる実践つき。

stat unit を出したら Game が 18ms もあった。CPUが原因なのは分かった。でも、そこから先に進めません。どのActorの、どの処理が重いのかが分からないからです。

stat は「どこが詰まっているか」までを教えてくれる道具で、そこから先は担当が変わります。Unreal Insights は、ゲームの実行を丸ごと記録して、後から1フレームの中身を関数単位まで開いて見るためのツールです。この記事では、トレースの取り方、Timing Insightsの読み方、そして呼び出しの入れ子をたどって自分のBlueprintにたどり着くまでを解説します。

statで当たりを付け、Unreal Insightsで重い処理を特定する様子とソフトブルーのクレイ人形

この記事でわかること

  • stat と Insights の 役割の違い
  • トレースの記録方法(エディタから/起動引数から)
  • 🚨 自分のBlueprint名を出すには -statnamedevents
  • Timing Insights で1フレームを開く
  • 呼び出しの入れ子をたどって 自分のBlueprintを見つける
  • Memory Insights で何がメモリを食っているか
  • 実践: statで当たりを付けて、Insightsで確定させる

Sponsored

statで分かること、分からないこと

statコマンド は、画面に出しっぱなしにして今の状態を知るための道具です。stat unit なら Frame / Game / Draw / GPU の4つが出て、どこが詰まっているかまで分かります。

分からないのは、その先です。

statは「Gameが18ms」までしか分からず、Insightsは「BP_EnemyのTickが12ms」まで降りられることを左右で対比した図
statコマンドUnreal Insights
見えるものどのスレッドが詰まっているかどの関数が何ミリ秒使ったか
粒度スレッド単位・機能単位呼び出し1つ単位
見るタイミング実行中にその場で記録して、後から
得意なこと当たりを付ける確定させる

つまり、この2つは競合しません。stat で当たりを付けて、Insightsで確定させるという順番で使います。

stat unit の Game が大きいなら、CPU側のゲームロジックが重いということです。Insightsを開けば、その18msの内訳が関数ごとの帯として見えます。


トレースを記録する

Unreal Insightsは、「記録するツール」と「見るツール」が別になっています。まずゲームを動かしながら記録し、その記録ファイル(.utrace)を後から開きます。

起動引数に-statnamedeventsを付けて起動し、CPU/Frameチャンネルで記録し、.utraceを保存してからUnreal Insightsで開いてBP_Enemy_Cを見るまでの流れ図

いちばん手軽なのは、エディタのステータスバー右下にあるトレース用のボタンから記録を開始する方法です。押すと記録が始まり、もう一度押すと止まります。止めた時点で .utrace ファイルが保存されます。

記録するときに選ぶのが チャンネル です。「何を記録するか」の指定で、全部入れると重くなるので、目的に応じて絞ります。

チャンネル記録されるものいつ使うか
CPU関数の呼び出しと所要時間まずこれ。処理が重いとき
GPU描画の所要時間stat unit の GPU が大きいとき
Frameフレームの区切り常に入れる(時間軸の目盛りになる)
Memoryメモリの確保と解放メモリを調べるとき(後述)

まずは CPU と Frame だけで十分です。 全チャンネルをオンにすると記録そのものが重くなり、測りたい負荷が埋もれます。

記録した .utrace は、Unreal Insightsアプリ(エンジンのインストール先にある独立したアプリ)で開きます。エディタから記録した場合、ボタンの近くから直接開けることもあります。

測るときはエディタから離れる。 精度が必要なら、エディタのPlayではなく Standalone Game か、パッケージした Development ビルド で測ってください。エディタのPlayには、エディタ自身の描画やツールの負荷が混ざります。

自分の名前が見える状態にする

ここで先に済ませておくことがあります。そのままだと、自分が作ったBlueprintの名前が出てこないことがあります。

標準の記録では、エンジン内部の処理名が中心になります。BP_Enemy_C のような自分の名前まで出すには、名前付きイベント(Named Events)を有効にした状態で記録する必要があります。

起動引数に -statnamedevents を付けて起動するのが、いちばん確実な方法です。

MyGame.exe -statnamedevents

そして重要なのが、本題の調査に入る前に、名前が出るかどうかだけを確かめることです。

  1. -statnamedevents を付けて起動する
  2. 5秒だけトレースを記録する
  3. Insightsで開き、BP_ で始まる名前がどこかに出ているかを見る
  4. 出ていなければ、起動引数とチャンネル設定を見直す

この確認を飛ばすと、「重い処理が見つからない」のか「名前が出ていないだけ」なのか区別できません。 30秒で済む確認なので、必ず先にやってください。

どこまで細かく見えるかは環境で変わります。 BP_Enemy_C までは出ても、その中の Get All Actors Of Class まで出るかは記録設定によります。まずBlueprint名まで特定できれば十分です。そこから先を絞りたければ、そのBlueprintを開いてノードを見るか、追加の名前付きイベントを仕込みます。

Sponsored

Timing Insightsの読み方

.utrace を開くと、いくつかタブがある中の Timing Insights が主戦場です。

Timing Insightsの画面構成。上のタイムラインでフレームを選び、下のトラックに関数の帯が入れ子で並ぶことを示した図

見る場所は3つです。

場所何が見えるか
上部のフレーム一覧各フレームの長さが棒グラフで並ぶ。 突出して長い棒=カクついた瞬間
中央のトラックGameThread / RenderThread などの行。 関数の呼び出しが横長の帯 として並ぶ
下部のパネル選んだ範囲の集計。 どの処理が合計何ミリ秒か が表で出る

使い方の基本は、上部で「長いフレーム」を見つけて、そこを選ぶことです。平均を眺めても、カクつきの原因は見つかりません。いちばん長い1本を狙い撃ちします。

フレームを選ぶと、中央のトラックがその瞬間の中身に切り替わります。ここに並ぶ横長の帯が、実際の処理です。

  • 帯の長さ=その処理にかかった時間
  • 帯の下にぶら下がっている帯=その処理から呼ばれた処理

つまり、上の階層から下へ降りていくと、時間を使っている犯人に近づきます


重い処理へ降りていく

ここがこのツールの本体です。幅の広い帯を、上から順に開いていきます。

幅の広い帯を選んで展開していくと、Tickの下にBP_Enemyの関数が現れ、その幅が全体の大半を占めていることを示した図

手順は単純です。

  1. いちばん幅の広い帯を見つける(FEngineLoop::Tick のような、大枠の名前が出ます)
  2. その帯を 展開して、下の階層を見る
  3. また いちばん幅の広いものを選ぶ
  4. 自分が付けた名前が出てくるまで繰り返す

BP_Enemy_CUpdateHealthBar のような、自分で名付けたものが出てきたら、そこが原因です。エンジン内部の名前しか出てこないうちは、まだ降り方が足りません。

同じ名前がたくさん並んでいたら、数が問題です。 1つ1つは短くても、BP_EnemyTick が200個並んでいれば合計は大きくなります。この場合は処理を軽くするより 呼ぶ回数を減らす ほうが効きます(→ Tickに頼らない設計)。


Memory Insightsでメモリを見る

処理時間ではなくメモリを調べたいときは、Memoryチャンネルを有効にして起動する必要があります。

ここはCPUの記録と手順が違います。 メモリの記録はプロセスが立ち上がった瞬間から有効になっていないと、それ以前の確保を追えません。あとからUIで記録を始めても、起動時に何が載ったかは分かりません

MyGame.exe -trace=default,memory

起動引数でこう指定してから遊び、そのトレースを開きます。

見えるのは、 「いつ、何が、どれだけメモリを確保したか」 です。使いどころは主に2つです。

  • 起動時に何が読み込まれているか — 使っていないはずのアセットが載っていないか(→ ソフト参照と非同期ロード
  • プレイ中にメモリが増え続けていないか — 破棄し忘れたActorやWidgetがないか

Memoryチャンネルは記録が重くなるので、CPUの調査とは分けて取るのが実用的です。「今日は処理時間、明日はメモリ」と目的を分けてください。

Sponsored

実践:カクつくレベルの原因を突き止める

大量の敵が湧くウェーブ防衛、オープンフィールドの探索パート、弾幕シューティング。「特定の場面だけカクつく」 は、どのジャンルでも同じ手順で追えます。ここでは stat で当たりを付け、Insightsで確定させるまでを通しでやります。

再現する状態を作る

原因を特定するには、確実にカクつく状態が要ります。手元に無ければ、次を作ってください。

用意するもの内容
BP_EnemyStatic Meshを持つActor。Event TickGet All Actors Of Class(対象: BP_Enemy)を呼び、返ってきた配列の長さを変数に入れるだけ
配置数レベルに BP_Enemy を200体 並べる
計測環境Standalone Game-statnamedevents 付きで起動(エディタのPlayではない)

Get All Actors Of Classレベル全体を走査する重い処理です。それを200体が毎フレーム呼ぶので、確実に重くなります(これは よくあるミス の定番でもあります)。

statでGameが18msと出た状態から、Insightsで長いフレームを開き、Tickを展開してBP_Enemyを特定するまでの流れを示した実例図

手順

  1. Standaloneを -statnamedevents 付きで起動し、コンソールに stat unit と入力する。Game が突出して大きいことを確認する(Draw と GPU は小さいはず)
  2. カクついている状態のまま、トレースの記録を開始する。チャンネルは CPU と Frame
  3. 5秒ほど記録して停止し、保存された .utraceUnreal Insights で開く
  4. まず名前が出ているかを確認するBP_ で始まる項目がどこかにあれば準備OK(無ければ起動引数を見直す)
  5. Timing Insights タブを開き、上部のフレーム一覧で いちばん長いフレームを選ぶ
  6. GameThread のトラックで、いちばん幅の広い帯を展開していく
  7. Tick の下に BP_Enemy_C が並んだら特定完了。そこまで来れば、直す対象は決まります

確かめる

うまくいっていれば、stat unit の Game が示していた時間の大半が、BP_Enemy の Tick に集まっているのが見えます。1体あたりは0.05msでも、200体並べば10msです。stat では「Gameが重い」としか分からなかったものが、どのActorのせいかまで確定します

BP_Enemy_C まで来たら、あとはそのBlueprintを開いて Event Tick を見ればいいだけです。「重いのはこのActor」まで絞れれば、中身は目で追えます。

ここまで来たら、直し方は決まります。Get All Actors Of Class を毎フレーム呼ぶのをやめ、必要なときだけ取得して変数に持つか、Tickそのものをやめる。直したらもう一度同じ手順で測り、Game の数値が下がったことを確認してください。

うまくいかないときの切り分けです。

  • エンジン内部の名前しか出てこない → 2つの可能性があります。-statnamedevents を付けずに起動したか、まだ展開が浅いかです。まず起動引数を確認し、それでも出なければ幅の広い帯をさらに下へ降りてください
  • どのフレームも同じくらいの長さ → カクつきではなく常時重い状態です。それでも手順は同じで、平均的なフレームを1つ選んで降ります
  • 数値がエディタで測ったときと違う → 正しい挙動です。Standaloneのほうが実際に近い値です

ポイントは2つです。

  • 平均ではなく、いちばん長い1フレームを見る: カクつきは「たまに起きる」ものなので、平均には埋もれます。上部のフレーム一覧で突出した棒を狙い撃ちしてください
  • 自分の名前が出る状態で測る: FEngineLoop::Tick が重いと分かっても何もできません。-statnamedevents を付けて BP_Enemy_C まで降りて初めて、直す対象が決まります

数を減らす方向で直すなら LODとカリング、生成と破棄が多いなら オブジェクトプーリング が次の担当です。


おまけ:先に知っておくと良いこと

Shipping以外なら大体取れる。 トレースは Development ビルドでも取れます。実機に近い環境で測りたいときは、パッケージした Development ビルドを実機で動かして記録するのが最も正確です。

起動引数は3つ覚えれば足りる。 -trace=cpu,frame(何を記録するか)、-statnamedevents(自分の名前を出す)、-trace=default,memory(メモリを記録する)。起動直後の重さを測りたいときは、UIのボタンでは間に合わないので引数で始めます。

記録ファイルは大きくなる。 .utrace は数秒で数百MBになることがあります。調べ終わったものは消しておかないと、ディスクをじわじわ食います。

「測ってから直す」を癖にする。 体感で「たぶんこれが重い」と思って直しても、外していることがよくあります。直す前に測り、直した後にもう一度測る。 この往復が、最適化でいちばん確実な進み方です。


まとめ

  • stat は当たりを付ける道具、Insightsは確定させる道具。順番に使う
  • 記録は CPU と Frame チャンネルから。全部入れると記録自体が重くなる
  • 🚨 自分のBlueprint名を出すには -statnamedevents 。本題の前に「名前が出るか」だけ確認する
  • 🚨 メモリは -trace=default,memory で起動時から 。あとから記録を始めても起動時の確保は追えない
  • Timing Insightsでは いちばん長いフレームを選ぶ。平均では見つからない
  • 自分が名付けたもの(BP_Enemy_C など)が出るまで降りる
  • 精度が要るなら Standalone か Development ビルド で測る

stat unit の Game が大きい、で止まっていた調査が、Insightsを開けば関数名まで届きます。あなたのプロジェクトでいちばん長いフレームは、何をしている瞬間でしょうか。