[UE5] Using the Blueprint Debugger: Breakpoints and Stepping

Created: 2025-12-12Last updated: 2026-09-05

Pause Blueprint execution and find where a value changes. Using a reproducible zero-damage bug triggered by the F key, we work through breakpoints, Step Into/Over, Watch, and Debug Object to fix HP 100 → 80.

The attack logic is being called, but the enemy's HP does not drop from 100. Even when Print String tells you "the damage passed was 0," it may not show you which calculation produced that 0.

That is what the Blueprint Debugger is for. It pauses just before the suspect logic so you can advance a little at a time and check values. It is the tool for investigating "why did it become that value" after the log has told you "what happened."

In this article we build a small example that deliberately sets the damage multiplier to 0. We follow it together through stop → inspect values → fix the setting → confirm HP drops from 100 to 80.

A figure pressing pause and inspecting the frozen game with a magnifying glass

What You'll Learn

  • How to stop just before a node runs with a breakpoint
  • How to choose your inspection scope with Step Into, Over, and Out
  • Why you distinguish "not yet run" when reading pin values and Watches
  • How to choose which instance of the same Blueprint to observe with Debug Object

Sponsored

Use logs and the Debugger according to what you want to know

Logs leave footprints you read later; the Debugger stops execution and inspects the scene
What you want to knowThe easier tool
Whether the attack logic ran, and how many timesPrint String and the Output Log
Which value was used and which branch was takenBlueprint Debugger
Observing mashing or timing intervals while it runsLogs or recording tools

Both let you inspect values. The Debugger lets you check pins and variables without adding a Print each time, and logs let you record progress without stopping the game. You can also narrow down the suspect area with the Print String article and pause where you want detail.

Timing-dependent bugs can change conditions when you pause or shift focus to the editor. If it stops reproducing when you pause, go back to taking logs while it runs.

A breakpoint marks "stop just before running"

A breakpoint marks "when execution reaches this node, stop before running it." Put them on Sets, Branches, and function calls with white exec lines.

  1. Right-click the node you want to stop at and choose "Add Breakpoint." The default shortcut is F9.
  2. Compile, save, and Play. Playing inside the editor like this is called PIE (Play In Editor).
  3. Perform the action that calls that logic. On arrival it pauses and highlights the node.

The important part is that the node you stopped at is about to run. If you stopped at Set Health, that Set has not rewritten HP yet.

Stopped at Set Health. Since it is about to write 80, Health is still 100

Pure nodes with no white exec line, such as an addition or a variable Get, are computed when the side using the value needs them. Rather than trying to put a mark there, stop at the Set that uses the result or at the function call that computes it.

Mark states and how to open the Debugger

An enabled mark is filled red; a disabled one is just an outline. A yellow "!" means it cannot validly stop there. Compiling sometimes clears it; if not, hover the mark to see the reason.

To see the list and Watches, open "Blueprint Debugger" from Tools in the main editor. You can also open it from the Blueprint editor's Debug menu. Breakpoints work even without opening the dedicated window.

Stepping: in, over, and out

While paused, the toolbar's step operations advance execution. Learning the name of each operation lets you use them in environments with different key bindings.

Step Into goes inside the function, Step Over continues on the calling side, and Step Out finishes the current function and returns to the caller
OperationWhat happensWhen to use it
Step IntoAdvances and enters a Blueprint functionYou want to inspect the calculation
Step OverRuns the current logic and continues without tracing inside a functionYou only need that function's result
Step OutRuns the rest of the current function and returns to the callerYou are done inspecting inside
ResumeReturns to normal executionYou want the game to continue

Both Over and Out run the logic. They do not rewind or undo a function's effects. You may also stop again at another breakpoint along the way.

Assignments such as F10 and F11 can be checked in "Editor Preferences" → "Keyboard Shortcuts" by searching Step Over / Step Into. The hands-on below is fine to work through with the toolbar buttons.

The debugger cannot rewind, so if you miss something, place a breakpoint earlier and repeat the same action. Choosing your scope — Into only the suspect functions and Over the confirmed ones — makes it easier to follow.

Reading values: hovering pins and Watch

While paused, hover a data pin to check its value. But what is shown is the value from the last time that node ran. The output of a node that has not run yet does not hold this pass's result.

For example, when you stop just before calling the damage calculation, the result does not exist yet. Seeing "cannot display value" there does not mean the damage is 0. Run the logic you need, then look again.

Pins that have run show values, while pins that have not run yet cannot be checked

Watch is a feature that registers pins you want to check repeatedly into a list. Right-click a pin name and choose "Watch this value" to follow it in the Debugger. This too cannot show values that have not run.

We use this distinction in the hands-on next. We store the calculation result in a variable inside the function and, once that runs, inspect the two values that were multiplied.

Debug Object: which instance to observe

Place three of the same BP_Enemy and each of the three holds its own HP. An actual object created from the Blueprint plan like this is called an instance.

Observing one enemy chosen with the Debug Filter among several of the same kind

The Blueprint editor's Debug Object is the field for choosing what to observe. To start, restricting the target to one instance as in the hands-on avoids mixing up values from a different instance.

With several instances, press Shift + F1 during Play to return the mouse to the editor and choose the running instance you want from Debug Object. Use the Actor name you set in the level as your clue. Settings or run state can also cause a target to be selected, so rather than assuming "nothing was selected," confirm the current name.

Choosing a target does not send the attack to that Actor. What matters is aligning the object your game logic acts on with the object you observe in the Debugger.

Sponsored

Hands-On: investigating why damage becomes 0

Pressing F sends one round of damage logic to a practice enemy. At first the multiplier is 0, so HP does not drop. We confirm that 0 in the Debugger, then fix the multiplier to 1.

At multiplier 0, 20 × 0 leaves HP at 100; fixing it to 1 makes 20 damage bring HP to 80

Create a UE5 Third Person template in Blueprint, choosing None if there is a Variant option. Work in a new practice folder. We prepare no attack animation or collision, so the same conditions can be repeated with a key press.

1. Prepare the practice enemy and variables

Create BP_DebugDamageEnemy with Actor as parent. Add a Static Mesh under DefaultSceneRoot, set the standard Cube, and set relative location and rotation to 0 with Scale 1. Cube can be selected from Engine/BasicShapes with "Show Engine Content" on. Set Collision Presets to NoCollision and turn off Simulate Physics.

Create the following variables, Compile, and set defaults. Leave Instance Editable off.

VariableTypeDefaultMeaning
HealthFloat100The current HP
BaseDamageFloat20Damage before the multiplier
DamageMultiplierFloat0The damage multiplier. Our deliberate bug

A multiplier represents how many times the original amount to apply. 1 keeps 20 damage, 0.5 makes it 10, and 0 makes it 0. Here we investigate a settings mistake: "it should be 1 for a normal attack, but it was 0."

2. Create the calculating Function

Create Function CalcPracticeDamage with Pure off so it can be called on a white exec line. Add Damage to Outputs as a Float. Under the function's Local Variables, create CalculatedDamage as a Float with default 0.

CalculatedDamage is a temporary variable belonging only to this function where the result is parked once. We place that intermediate Set so we can stop before and after the value is stored.

  1. Connect the function entry's white line to Set CalculatedDamage.
  2. Place a Float multiply * and pass Get BaseDamage to A and Get DamageMultiplier to B.
  3. Pass the multiply result to Set CalculatedDamage's value.
  4. Connect the Set's white output to the Return Node and pass Get CalculatedDamage to Return's Damage.

The Return Node is the exit that hands the computed value back to the caller. Call this function and you receive the result from the Damage output.

Multiplying BaseDamage and DamageMultiplier, storing it in the Local variable CalculatedDamage, and returning it from the Damage output

3. Reduce HP with the returned result

Create a Custom Event ApplyPracticeHit in the Event Graph. From this event, call your CalcPracticeDamage and connect Set Health after it.

The value fed into Set Health is a Float subtraction of Get Health − CalcPracticeDamage's Damage output. Pass that through Max (Float) with the other input set to 0 so HP never goes below 0.

Subtracting the function's Damage output from Health, keeping it at 0 or above with Max, and passing it to Set Health

The "from" and "to" in the diagrams are pointers showing how it connects to the diagrams before and after. You do not add nodes with those names.

Place a Print String after Set Health. Pass Health: to Append's A and Get Health converted with To String (Float) to B, then connect the Return Value to Print String's In String. Set Duration to 10 seconds.

To String turns the number into text and Append prefixes it with Health: . What the Print reads is Health after the Set. That lets you confirm on screen "what HP became as a result of calling it." We add no logic to destroy the enemy at 0 HP.

Converting the updated Health to a string, prefixing it with a Health label, and displaying it for 10 seconds with Print String

4. Make F call the same logic

Compile, save, and place one BP_DebugDamageEnemy in front of the Player Start. Set the Actor's Scale to 1 with its center about 50 cm above the floor. Renaming it to DebugEnemy in the Outliner makes it easier to find later.

  1. With the placed DebugEnemy selected, open "Open Level Blueprint" from the level's Blueprint menu.
  2. Right-click in the graph and create "Create a Reference to DebugEnemy" for the selected Actor.
  3. From that reference, create a node calling ApplyPracticeHit.
  4. Place a keyboard F event and connect Pressed to ApplyPracticeHit's white input. Target is the placed DebugEnemy reference.
From F Pressed in the Level Blueprint, calling ApplyPracticeHit with the placed DebugEnemy as Target

Compile, save, Play, click the game view, and press F once. Seeing Health: 100 means you reproduced the deliberate bug. Get this far, then stop Play.

5. Stop on the calling side and step into the function

Go back to BP_DebugDamageEnemy and put a breakpoint on the CalcPracticeDamage call node in the Event Graph. Right-click the node connected by the white line, not the name in the Functions list.

Putting a breakpoint on the CalcPracticeDamage called from ApplyPracticeHit. At the pause, this pass's calculation has not run yet

Start a new Play and press F once in the game view. When it stops at CalcPracticeDamage, confirm Debug Object points at the running DebugEnemy instance.

At this point this pass's Damage output has not been computed. Use Step Into to enter the function and follow along until Set CalculatedDamage runs. If you stop just before the Set, use Step Over to run it.

Gets and the multiply are evaluated when preparing the value passed to the Set. You do not step through every small node on screen one by one.

6. Confirm the values used in the calculation

Once Set CalculatedDamage has run and you advance to the Return Node, hover the output pins of Get BaseDamage and Get DamageMultiplier feeding the multiply.

Value to readThe result we want to confirm
BaseDamage's output20
DamageMultiplier's output0
The multiply result0

The original damage of 20 is correct, and since the multiplier is 0, the product is 0 too. You learn that the calculation node is not broken — the setting fed into the calculation is wrong.

Here, right-click DamageMultiplier's output pin and choose "Watch this value." Check the value in the Blueprint Debugger so you can compare the same pin on the next attempt.

If you overshot the spot you wanted, put a breakpoint on the Return Node too, restart Play, and press F. Resuming from the calling side stops you just before Return with the Set already done. If no value appears, confirm whether the node has run and whether the target instance matches.

7. Fix the multiplier and repeat the same action

Stop Play. Change BP_DebugDamageEnemy's DamageMultiplier default to 1, then Compile and save. Do not stop at changing only a temporary in-game value.

Start a new Play and press F once. Stepping into the function the same way, this time BaseDamage is 20, DamageMultiplier is 1, and the multiply result is 20. Confirm in the Watch too that the evaluated multiplier is now 1.

Resume, and if you stop at other breakpoints, continue again. Seeing Health: 80 means the corrected calculation reached HP.

Try 0.5 as well: pressing F once in a new Play gives 10 damage and Health: 90. Afterwards, set the multiplier back to 1 and delete or disable the breakpoints you no longer need.

Restarting Play each time is to reset Health to 100 for comparison. Press F repeatedly within the same Play and the next damage applies to the already-reduced HP.

When it doesn't stop, or values don't appear

SymptomWhere to check
Pressing F does nothingWhether input is going to the game view, the level's F Pressed and Target on the placed Actor
Print appears but it doesn't stopThe breakpoint's enabled state, Compile, the current Debug Object
A yellow "!" appearsThe mark's hover explanation. Whether it is on an exec node rather than a pure node
No value shows on a pinWhether the logic using that Get or calculation has already run this pass
Multiplier changed to 1 but still 0Whether you stopped Play and edited the default, whether you compiled and saved, whether you are looking at a different instance
Sponsored

Bonus: Good to Know Up Front

Use the Call Stack to see where you were called from

The Call Stack is the history of "which function led into the current one." The function currently running sits at the top. It helps when several similar entry points exist and you are unsure which one called you.

Execution Trace, meanwhile, is a list of recently executed nodes. Look here when you want to follow the nodes you passed through. Open the panels you need in the Blueprint Debugger and confirm rather than relying on the glow of exec lines alone.

Stop where Accessed None happens

Accessed None is the error you get when using a reference that points at nothing. Search "Editor Preferences" for Blueprint Break on Exceptions and enable it to stop where such exceptions occur. It is under Experimental's Blueprints.

Since it stops more often, use it while investigating reference problems. To inspect inside a Component, also confirm the Component instance owned by that Actor in Debug Object (the Component article).

Preserve the fixed conditions in an automated test

Here you could preserve "BaseDamage 20 with multiplier 1 returns 20" and "20 damage on HP 100 gives 80." The automated testing article covers how to verify expected results like these in Blueprint.

With a test in place, you notice when the same bug comes back under the same conditions. You can connect the roles: investigate the cause with the Debugger, and confirm repeatedly with the test.

Summary

In the Blueprint Debugger, you stop just before suspect logic and inspect values while advancing only the range you need.

  • The node you stopped at with a breakpoint is about to run.
  • Into enters, Over runs without tracing inside, and Out finishes the current function.
  • Pins and Watches show the most recent executed value. Do not mistake "not yet run" for 0.
  • Use Debug Object to align the object your game acts on with the one you observe.
  • If you miss it, stop earlier and, after fixing, try again under the same conditions.

In the damage example we changed 20 × 0 to 20 × 1 and confirmed HP 100 → 80 at the end. Tracing back from a result to the ingredients that produced it is what gives you a lead on the cause.

If the graph is hard to follow, see 10 techniques for organizing; if you would rather search by common failures, see 10 Blueprint mistakes.

Further Reading

Unreal Engine Notes in this section98