You change a number in a parent Blueprint, compile it, and start the game. One guard walks faster. Another guard, apparently made from the same Blueprint, keeps walking at its old speed. Before changing another setting, select each actor and read its class name. Two guards can look identical while taking their starting speed from different places. An inherited field, a class default, a placed instance and a running movement component each answer a different question about the same guard.
This walkthrough follows one value from the parent asset to the actor that actually moves. Use a duplicate test map if your level already contains carefully tuned enemies. The aim is to find the first place where the expected and observed numbers disagree. Once you know that boundary, you can make a small repair without resetting unrelated properties across an entire level.
Build a test where the numbers tell you who wrote them
Create an Actor Blueprint named BP_SpeedProbe. Add a float named TravelSpeed, give it a default of 300, make it Instance Editable, compile and save. Create a child class from that asset and call it BP_SpeedProbeChild. Leave its defaults alone. Place one parent and two children side by side in a test level. Name the children Inherited and Tuned in the Outliner. On Tuned alone, set TravelSpeed to 425 in the level Details panel.
Open the parent Event Graph. At BeginPlay, print the actor’s display name followed by TravelSpeed. An Append or Format Text node can build a message such as “Tuned: 425”. Play the level and read the output for all three actors. In this deliberately empty setup the parent and Inherited should report 300, while Tuned should report 425. Nothing needs to move yet. You are testing the source of a value, so introducing a movement system at this point only gives you another place to look.
Stop play. Change the parent default to 350, compile, save, and repeat. Two readings should change together. The 425 reading is your control: it demonstrates that a level designer can keep a deliberate exception even when the family default changes. If you cannot reproduce those results, check the class and the selected world before copying any fix into the real actor.
Read the parent, child and instance in that order
Open the parent asset and check TravelSpeed in Class Defaults. Open the child asset and check the same field in its Class Defaults. Finally select Inherited in the level and inspect its Details panel. Write down all three readings on one line. A line such as “parent 350, child 300, instance 300” sends you to the child asset. A line such as “parent 350, child 350, instance 425” sends you to the level actor. There is no reason to edit the parent in the second case.
A child can have a deliberate class-wide exception. A heavy guard subclass might start at 220 even when ordinary guards move at 350. Every newly placed heavy guard should then start at 220 unless a designer tunes that specific actor. If all heavy guards share the old speed, inspect their child default before resetting individual actors. Resetting a placed heavy guard to its immediate default might correctly return 220. It does not ask the editor to skip the child class and jump straight to the top of the family.
Look for the reset control beside the individual property. Read its tooltip, inspect what value the UI proposes, and reset only the field you intend to inherit again. Record the old value first. A level actor often carries other intentional differences such as patrol distance or a reference to a particular door. Replacing the whole actor to fix one number can cost you those assignments and references elsewhere in the level.
Distinguish a missing variable from a stale value
If TravelSpeed does not appear in the child’s variable list, first inspect the My Blueprint panel’s view options and enable the display of inherited variables where available. Then check the parent definition and access settings. A hidden entry in an editor list tells you little about which number a running actor holds. Find the existing field before adding anything with a similar name.
A common detour is to add PatrolSpeed in the child and write movement logic using that new field while the parent logic still reads TravelSpeed. The child editor now shows the number you expect and the game continues using the old one. Follow the wire at the node that consumes the value. Open the variable definition from that node and compare it with the property you edited. Display names alone are weak evidence when a Blueprint contains older experiments.
The Instance Editable setting is useful if designers should tune placed actors independently. Expose on Spawn solves a different problem: it allows a caller to supply an initial value as the actor is spawned. Decide which workflow you actually want. A global balance change belongs in defaults or shared tuning data. A single slow guard belongs in that guard’s override. A speed chosen by a spawner belongs in its spawn inputs.
Compare an existing actor with a genuinely fresh placement
Drag the child class directly from the Content Browser into the level. Avoid duplicating a suspect actor for this test. A duplicate can carry the very instance override you are trying to isolate. Put the fresh actor next to the old one, give it an unmistakable label and compare Details before pressing Play. If only the old actor differs while the fresh one behaves correctly, the old actor’s saved properties deserve a closer look.
If both look right in the editor but differ at runtime, inspect the class actually present during play. A spawner may create a different subclass at nearly the same coordinates. A player pawn may come from the active GameMode even though you were inspecting another pawn placed in the map. Print the runtime object’s name and class next to its measured value. The question is which object generated the output, not which actor the viewport happened to show before play began.
For a crowded map, temporarily move your test actors to an empty corner and print to the Output Log. Avoid using a print on every Tick while investigating an initialization problem. A single line at each meaningful event is easier to read than hundreds of lines showing the last value after it has already changed.
Trace construction, BeginPlay and the first gameplay event
A correct value in Class Defaults can be overwritten by graph logic. In the real Blueprint, search for setters of the property. Put a breakpoint on each relevant setter, choose the exact running instance in the Blueprint debugger and trigger the behaviour once. At each break, inspect the incoming value and the target object. If you find several writers, write down the order in which they execute during your reproduction.
Suppose the child default is 450. At BeginPlay the parent loads a difficulty profile that supplies 320. Later a sprint function multiplies the current rate by 1.5. The first sprint now produces 480. Setting the child default to 500 and retrying will still produce 480 if the difficulty profile overwrites it again. Investigate the assignment of 320. The multiplier is doing exactly what the values it received told it to do.
Construction Script is also worth inspecting, particularly when its logic derives values from components or other editable fields. It can run again as you make editor changes. Keep diagnostic prints for construction separate from prints during play. If a designer is meant to control TravelSpeed, a construction graph that writes a constant into it can make the Details panel deeply misleading. Prefer computing a separate derived field when the original input needs to remain available for editing.
Check the component that actually consumes the value
Return to the guard example. TravelSpeed is a variable you invented. Character Movement has its own Max Walk Speed property. Changing TravelSpeed does not automatically change that component property. Follow the graph to the point where one is copied into the other. If the Blueprint prints TravelSpeed correctly but the character still moves at the old pace, read Max Walk Speed from the same character immediately before and after the assignment.
Give the component a conspicuous test value, such as 150, then 600. Use the same stretch of level and the same movement mode for both passes. Acceleration, input strength, collisions, slopes and braking can all affect instantaneous velocity. Compare a steady stretch of unobstructed movement. A speed cap is a limit; the character does not have to reach it on the first frame after input begins.
A similar split appears in UI. A health bar might read CurrentHealth while the child default you changed is MaxHealth. A widget that captured a value once when it opened can remain stale after the actor changes. In that case the class hierarchy can be entirely correct. Log the actor value and the widget input at the same gameplay event before making another inheritance edit.
Give configuration and changing state separate names
For a health system, try MaxHealth as the starting configuration and CurrentHealth as the running value. Initialize CurrentHealth deliberately when a new actor begins its life. Damage changes CurrentHealth. A health pickup restores part of it. A child enemy can override MaxHealth without accidentally specifying the remaining health of an actor already in combat. Make the names reflect those roles wherever the values are read.
Consider what should happen after loading a save. A new guard should start at full health, but a returning guard might have 35 health because the player injured it earlier. If your initialization graph sets CurrentHealth from MaxHealth after loading, it erases the restored state. If loading runs afterward, it can make a recent balance change appear ineffective. Test a fresh game and a loaded game separately and label those log entries. Both outcomes may be correct for different starting conditions.
Do the same with speed modifiers. Keep BaseSpeed separate from the effective speed after equipment, difficulty or temporary effects. Recalculate from the base when a modifier changes. Multiplying the previously modified value repeatedly makes the outcome depend on how often an event ran. That can resemble an inheritance bug because only some actor instances happened to receive the event twice.
Reduce the failure to one change you can reverse
Keep a tiny test matrix: parent placement, untouched child placement, overridden child placement and spawned child. Record the expected number, the observed number and the first event at which they disagree. Include a run after closing and reopening the saved test map. This catches the difference between an edit made during Play in Editor and an edit saved into the level or Blueprint asset.
If the small test works but the production map fails, bring systems across one at a time. Start with the child class, then its components, then the spawner or difficulty manager, and finally any save-loading path. When a single addition changes the result, you have a much narrower investigation. Keep the failing test case until a clean editor restart still gives the intended behaviour. For the exact distinction between reading class defaults and working with an instance, consult Epic’s Blueprint Class Defaults guide.
Common questions
Should I compile the child after editing the parent?
Compiling and saving both assets is a sensible baseline while tracing a change. It removes an avoidable source of confusion about which edits were applied. It does not express the design decision to discard an intentional override. Check the individual field after compilation and compare it with a freshly placed child before doing anything more invasive.
Why does resetting a level actor still give me the old number?
Its immediate class can have its own default. Inspect that child’s Class Defaults first. If the child correctly represents a slower enemy type, resetting the level actor to the child’s slower value is the intended result. Change the child only if every ordinary instance of that subclass should inherit a different baseline.
Why does only the second player see the wrong value?
First establish that the server and client are logging the corresponding actor and the same stage of its lifetime. In a networked game, a server-side state change and a local class default are different sources of information. Inspect the replication settings and the graph that applies the value on the receiving side. Reproduce the single-player case separately before changing network behaviour.
What would count as a finished fix?
Change the parent once more. Verify that the untouched child follows it, the tuned child keeps its intentional exception, and a newly spawned actor starts with the documented value. Then play through the event that originally exposed the fault. If the movement, UI or saved state now behaves correctly too, you have verified the whole path from asset to gameplay.