Movement got heavy in a scene with more enemies. stat unit shows Game time is long. You want to investigate game-side logic, but cannot tell whether it is AI or a per-frame search. That is when you use Unreal Insights .
It records what the game did while running so you can later investigate "what was happening during this stretch". Rather than staring at the screen so you do not miss a number, you can return to the moment that bothered you and find the logic that took time.
This article starts from opening a short recording. Then it covers reading the timeline and aggregation, and compares before and after on a small example that repeats the same Actor search every frame.
What You'll Learn
- Recording a trace and opening the saved file
- Settings that record Blueprint names and what to check when they are missing
- Reading nesting, Inclusive versus Exclusive, and call counts
- Narrowing candidates from a recording and fixing while preserving behavior
This assumes Windows UE5 and uses Blueprint variables, functions, and node connections. It also uses the idea of comparing at the same place, quality, and FPS cap from the stat unit article. The figures are schematics and the measurements are illustrative.
What Insights records
A trace records the starts and ends of work along with timestamps. Unreal Insights presents that record as timelines and tables. It is not video footage but a way to see what work the game did internally.
| Tool | Where to start using it |
|---|---|
| stat unit | Watch times while running to narrow down whether Game, Draw, or GPU is responsible |
| Unreal Insights | Return to the stretch where the problem occurred and investigate the recorded work and its breakdown |

One bar in Insights is a recorded interval of work. That is called a timing event . The name aggregating events of the same kind is a timer . That is a different meaning from Blueprint's Timer, which "runs after a set time".
Not every function and Blueprint node is recorded automatically. You see the record channels you enabled and the instrumentation prepared in the engine and code. Treat names you find as clues for investigation and go on to compare before and after a fix.
Record a short trace and open it
At first, saving a few seconds from a project you have, such as Third Person, is enough. So the recorded game and destination are unambiguous, we pass launch arguments to Standalone Game here.
Launch arguments are extra settings passed when starting the game. They differ in where you type them from commands entered into the console during play.
1. Specify the destination and record channels
Create a folder for recordings in Explorer. The example below uses C:/UETraces . Match the argument path if you use another location.
Open "Edit → Editor Preferences → Level Editor → Play" and enter the following into Additional Launch Parameters for "Play in Standalone Game". Note your existing settings and keep unrelated arguments. If an argument with the same name already exists, change it rather than duplicating it.
-trace=cpu,frame,bookmark,AssetLoadTime -statnamedevents -tracefile="C:/UETraces/insights-test.utrace"
| Specification | Its role here |
|---|---|
cpu | Records CPU work intervals |
frame | Records frame boundaries |
bookmark | Enables leaving markers on the timeline |
AssetLoadTime and -statnamedevents | Enables additional named instrumentation including Blueprint names |
-tracefile=... | Specifies the file the recording is saved to |
The record items listed after -trace= , such as cpu and frame, are called channels . Rough CPU investigation can start from cpu and frame, but we add more because we also want Blueprint names.

The name AssetLoadTime suggests asset loading, but the official procedure for recording Blueprint names uses it too. Do not stop at adding -statnamedevents ; specify them together.
2. Run in Standalone and stop recording
- Choose Standalone Game in the "Play" menu and launch.
- Once loading settles, do your usual actions, such as walking for a few seconds.
- Enter
Trace.Statusin the game console to confirm the recording state and enabled channels. - Enter
Trace.Stopto stop recording and quit the game. - Confirm
insights-test.utraceappeared in the specified folder.
Opening the console follows the stat unit display steps. .utrace is the trace file format. Getting a file means the recording side is ready.
Reusing the same name makes it easy to mix up before and after, so for real comparisons split them as before.utrace and after.utrace .
3. Open it in Unreal Insights
Open Unreal Insights (Session Browser) from the "Trace" menu at the bottom of the editor. On Windows, launching Engine/Binaries/Win64/UnrealInsights.exe from the engine in use directly is also fine.
Session Browser is the first screen for choosing a recording. Choose "Open File" from the arrow beside "Open Trace" and open your saved .utrace . Dragging the file from Explorer onto this screen works too. Once analysis progresses, Timing Insights for investigating processing time appears.
The editor's Trace menu also has "Start Trace" and "Stop Trace". Those help when measuring the editor itself, but do not confuse them with the separately launched Standalone recording. Our procedure records via the arguments passed to the game.
Confirm Blueprint names were recorded first
Drag the time ruler at the top of Timing to select the range you actually played. Search the Timers list for part of a Blueprint name you drove. For Third Person that might be BP_ThirdPersonCharacter , or BP_SearchProbe for the exercise below. A suffix such as _C can appear. How to read each panel is organized in the next section.
Displayed names and granularity vary with UE version, the logic, and settings. Do not expect a node name such as Get All Actors Of Class to appear at every level.
| When you cannot find it | What to check |
|---|---|
| There are no CPU bars at all | Whether you recorded cpu. Whether the CPU track is hidden |
| Engine names appear but no Blueprint names | Whether AssetLoadTime and statnamedevents reached the game you measured |
| Name searches come up empty | Whether you selected a time when the target ran. Whether search or display filters are too narrow |
| You opened a recording from old settings | Confirm the output path and file name and take a short recording again |
Names not in the recording never appear no matter how deep you dig later. Confirm your setup with a short test recording before investigating a heavy scene.
Choose the time to investigate in Timing Insights
The screen has many items, but start with three. Panel layout is configurable, so find them by name.
| Panel | What you look at |
|---|---|
| Frames | Each frame's length. Tall bars are frames that took time |
| Timing | Bars and nesting laid out on rows such as GameThread |
| Timers | Counts and total times of the same kind of work within the selected range |

GameThread is the CPU thread advancing the game. A track is a row laying out work per such responsibility. Horizontal is time and a bar's width is how long that interval took.
Choose the scene with the problem, not "the tallest bar"
If it only stutters the moment enemies appear, look at that moment and around it. If it is always heavy, select a few seconds of normal play after loading. Even when startup or the moment you opened the console is longest, that is not necessarily the problem you are investigating.

- Click the frame of interest in Frames. For several, click the first and
Shift-click the last. - Dragging the time ruler at the top of Timing also selects a range.
Fzooms the selection to a readable width; adjust with the mouse wheel if needed.- Hover over bars on the track you are investigating, such as GameThread, and read names and durations.
Changing the range changes Timers' aggregation too. Whether the table's "12 ms total" is one frame or five seconds is judged together with the selected range.
Read the breakdown from nesting and aggregation
Within the same track, bars drawn beneath another bar represent work done inside that logic. Above is the parent and below the child. Rows merely stacked from different threads are not necessarily parent and child.
Do not double-count parent and child times
With a 12 ms parent whose child took 8 ms, the remainder excluding the child is 4 ms.
| Display | Meaning | In this example |
|---|---|---|
| Inclusive (Incl) | Time including child work | The parent is 12 ms |
| Exclusive (Excl) | The remainder excluding recorded children | The parent is 4 ms |

Do not add the parent's 12 ms and the child's 8 ms into 20 ms. Even with a large parent Inclusive, when most of it is the child, investigate the child's breakdown. When Exclusive is large, check that interval's code or work not yet finely recorded.
Some bars are long because of waiting. Width alone does not mean lightening that function's computation will speed things up.
Separate one long call from many short ones
In Timers, look at Count as well as duration. At 0.05 ms each, 200 calls in the selected range total 10 ms. That is a reading example, not a measured value for a particular Actor.

Count is the number of events recorded within the selection, not the number of Actors. It can combine one Actor called across many frames and several Actors of the same kind.
On versions where Timers has aggregation modes, choose Instance first and read Count and total time. Modes such as Game Frame aggregate per frame, so check the column descriptions too.
Trace callers and callees
Selecting a timer of interest lets Callers show "who called it" and Callees show "what it called". Those panels present the selection's aggregation as a tree.
Clicking bars in Timing and expanding tree branches are different operations. Rather than assuming "keep opening bars and you always reach your Blueprint", combine time, count, and the parent-child breakdown to find candidates.
Hands-On: reduce a per-frame search and compare
We build a small experiment counting how many Actors of the same kind exist. The level does not gain or lose Actors after start. We compare counting every frame against counting once at start.

1. Build it up to reading a count with one Actor
In a Third Person Blueprint project, create BP_SearchProbe with Actor as the parent. Add a Static Mesh Component for visibility and specify Engine's basic Cube. Set Collision Presets to NoCollision and turn Simulate Physics and Cast Shadow off.
Create an Integer variable FoundCount with a default of 0. Then create a function RefreshPeerCount with no inputs or outputs and build these connections.
- The function's exec output → Get All Actors Of Class's exec input.
- Select BP_SearchProbe for Actor Class.
- Out Actors → the array's Length. Length returns the number of elements in an array.
- Get All Actors Of Class's exec output → Set FoundCount's exec input.
- Length's value → Set FoundCount's value.

Get All Actors Of Class gathers Actors of a specified class. With one BP_SearchProbe, the result is 1 including itself. More targets means more gathering work, so consider whether the same search needs repeating often.
In the Event Graph, first wire Event BeginPlay → RefreshPeerCount → Print String . Connect FoundCount's Get into "To String (Integer)" and pass that string into Print String's In String. Connecting the number pin straight into In String can insert the conversion node automatically. Set Duration to about 5 seconds.

As a separate path, wire Event Tick → RefreshPeerCount . Do not attach a Print String there. It displays once at start and merely recounts during play.

In Class Defaults' Actor Tick, turn Start with Tick Enabled on and set Tick Interval to 0. Compile, place one in the level, and Play; "1" appearing means the search and save work.
2. Multiply the same Actor and record the "before"
Stop and duplicate BP_SearchProbe with Alt-drag. Start from about 32 and increase in stages to 128 and 256 if needed. Duplicating a multi-selected group is fine.
At start, each Actor displays the count once. Make the time after the display clears and loading settles your investigation target. Also confirm Print String is not called every frame during measurement.
There is no rule that 200 Actors always make Game a certain number of ms. Even on a PC where the difference by count is small, you can practice how to record and how calls change.
Change the earlier launch argument's file name to before.utrace and launch in Standalone. Stay at the same start position and leave about five seconds of normal play before stopping with Trace.Stop . Keep channels, quality, and FPS caps the same before and after.
3. Look for work related to the search
Open the recording and select about five seconds avoiding startup. Search Timers for part of BP_SearchProbe or RefreshPeerCount and check the GameThread bars, Count, and Inclusive and Exclusive.
Blueprint names can appear as an aggregated timer. Check its contents in Blueprint and make the repeating search a candidate for investigation. Do not conclude the recording failed simply because node names do not appear.
4. Switch to counting once and re-measure
Turn Start with Tick Enabled off in BP_SearchProbe's Class Defaults. Keep the BeginPlay path and leave the Actor count and placement unchanged. Compile and save.
Now it counts and displays the same number at start and stops repeating the same search afterwards. Under our condition of "the count does not change after start", the saved number stays usable.
Change the file name to after.utrace and record under the same conditions. As before, select about five seconds avoiding startup and compare.
| What to confirm | The comparison point |
|---|---|
| BeginPlay's display | Whether the count is the same before and after |
| Bars during normal play | Whether Tick-driven repetition decreased |
| The same timer's aggregation | Whether count and total time decreased over the same range |
| Frame time | Whether the whole improved. Whether other work or caps limit it |

After stopping Tick, the target timer may disappear entirely from the selected normal-play range. If the start display confirms behavior and the "before" recorded under the same settings, that reads as the repetition being gone.
If needed, turn Tick back on, record, and confirm the original trend returns. That establishes the relationship between change and result better than simply calling a discovered name "the cause".
If enemies come and go in your real game, counting once at start leaves the information stale. Make it a fix that preserves the needed behavior, such as updating the count when enemies spawn and die. Choosing between Tick and Timer also helps decide that frequency.
Memory Insights is the entry point for memory
Processing time is measured in ms; memory is about the capacity holding data. Allocation is reserving a place and freeing is returning one you finished with. Memory Insights investigates when allocations happen and how long they remain.
Allocation and free tracking needs memory enabled from the moment the process starts . Make it a separate recording from normal CPU investigation.
Create a shortcut to a game packaged in Development and, in "Properties → Target", append the following after the executable, separated by a space. Create the destination folder first.
-trace=default,memory -tracefile="C:/UETraces/memory.utrace"
Launch the game, perform the actions you want to investigate, stop with Trace.Stop, and open the recording. Going to Memory Insights from Insights' menu shows allocation amounts over time and more.

At first, looking at how remaining memory changes "before entering a level" versus "after" narrows the goal. An increase alone does not mean a leak. Caches for later use and deliberately retained data exist too.
To split by asset and class name, also add metadata,assetmetadata . Reading function names may require debug information matching the build. For detailed reading, continue to the official Memory Insights, and when references pull in unneeded assets, consider soft references and async loading.
Bonus: good to know up front
Recording itself costs something
More channels and named events mean more recording work. Record short first and add to suit your investigation. Match record settings between before and after, and finally confirm behavior in normal play without recording.
Even without your own names, there is something to learn
Rendering waits, asset loading, and other threads' work can be involved. When you see gaps or long waits, rather than forcing your way toward a Blueprint name, switch the investigation to which responsibility it is waiting on.
Keep the recording and the conditions together
Note not just the file name but the Actor count, quality, resolution, caps, what changed, and the range you selected. Recording file size varies with duration and channels, so keep the before-and-after pairs you need and tidy the rest.
After experimenting, return Additional Launch Parameters to the settings you noted and restore any FPS cap you changed. For final confirmation in the shipping environment, record a Development build running on the target PC.
Next time you meet a heavy scene, decide which time to investigate before asking "which name looks suspicious". Lining up the scene, the breakdown, and before-and-after makes the next fix easier to reason about from the numbers.
Summary
- A trace is a tool for "recording and reading the file afterwards"
- Without settings that keep Blueprint names, you cannot tell which logic it is
- Inclusive includes the contents and Exclusive is that logic alone
- For things called many times, reduce the count rather than speeding up one call
The question to ask before looking is "is it thick because one call is heavy or because there are many calls?" The fix differs from there.
To grasp the whole first, see the stat command; for examples of reducing per-frame work, designing without Tick.
Reference: Trace, Command-Line Arguments, Timing Panel, Timers and Counters, Insights Reference.