Blueprints
Blueprints versus C++ in Unreal Engine — when to use which, performance tradeoffs.
12 questions
JuniorTheoryVery commonWhat is the difference between an Actor Blueprint and a Level Blueprint?
What is the difference between an Actor Blueprint and a Level Blueprint?
An Actor Blueprint is a reusable class you can instance many times across any level. A Level Blueprint is a single graph unique to one level, used for level-specific scripting and references to placed actors. It cannot be instanced or reused.
Common mistakes
- ✗Swapping the two roles — thinking the Level Blueprint is the reusable class
- ✗Believing a Level Blueprint can be instanced like an Actor Blueprint
- ✗Assuming Actor Blueprints are editor-only previews
Follow-up questions
- →Why can the Level Blueprint reference specific placed actors but an Actor Blueprint cannot?
- →When is it appropriate to script anything at all in the Level Blueprint?
JuniorTheoryVery commonWhen should you use Blueprints versus C++ in Unreal Engine 5?
When should you use Blueprints versus C++ in Unreal Engine 5?
Use Blueprints for rapid iteration, designer-friendly logic, and one-off gameplay. Use C++ for performance-critical systems, foundational engine extensions, and code that must be diff-able and unit-testable.
Common mistakes
- ✗Treating Blueprints as inherently slow without measuring.
- ✗Putting tightly-coupled gameplay code in C++ where designers can't iterate on it.
Follow-up questions
- →How do Blueprint nodes get compiled?
- →When does Blueprint VM overhead matter in practice?
JuniorTheoryCommonHow do you debug Blueprint logic in Unreal Engine 5?
How do you debug Blueprint logic in Unreal Engine 5?
Set breakpoints on nodes to pause execution and step through with watched variables. Use Print String and visual logger for live values, the Blueprint Debugger panel for call stacks, and pin-hover tooltips to inspect data flowing along wires.
Common mistakes
- ✗Not knowing Blueprint graphs support node breakpoints and stepping
- ✗Relying only on Print String when the Blueprint Debugger gives more
- ✗Thinking you must convert to C++ before any debugging is possible
Follow-up questions
- →What does the watch window add over hovering a pin to read its value?
- →How do you debug a Blueprint issue that only reproduces in a packaged build?
MiddleTheoryCommonHow do you avoid spaghetti Blueprints in a growing Unreal Engine 5 project?
How do you avoid spaghetti Blueprints in a growing Unreal Engine 5 project?
Split logic into small named functions and collapsed graphs, use event dispatchers instead of direct casts, and favor composition with components. Add reroute nodes and comment boxes, and move stable, heavy systems into C++ base classes.
Common mistakes
- ✗Keeping everything in one giant event graph instead of named functions
- ✗Overusing direct casts that create tight coupling between Blueprints
- ✗Centralizing references in the Level Blueprint as a global hub
Follow-up questions
- →Why do event dispatchers reduce coupling compared with direct casting?
- →How does moving logic into a C++ base class help keep child Blueprints clean?
MiddleTheoryCommonWhen should you move Blueprint logic into C++ in Unreal Engine 5?
When should you move Blueprint logic into C++ in Unreal Engine 5?
Move logic to C++ when it is performance-critical, runs every tick, must be reused as a base class, needs unit tests, or has grown too complex to diff and review. Keep designer-tunable, fast-iterating logic in Blueprints.
Common mistakes
- ✗Believing Blueprints cannot ship in a packaged build
- ✗Rewriting everything in C++ for marginal perf gains designers then can't tune
- ✗Thinking the choice is about disk size rather than performance and maintainability
Follow-up questions
- →How do you keep a C++ port designer-tunable after moving logic out of Blueprint?
- →What signals in a Blueprint graph suggest it is time to refactor into C++?
MiddleTheoryCommonHow do you structure a C++ base class with a Blueprint child in UE5?
How do you structure a C++ base class with a Blueprint child in UE5?
Put core logic and performance-critical systems in the C++ base class. Expose hooks via BlueprintImplementableEvent and tunable data via UPROPERTY(EditAnywhere), then create a Blueprint child to override visuals and tuning.
Common mistakes
- ✗Leaving the C++ base empty and writing all logic in the Blueprint child
- ✗Forgetting that overridable hooks need
BlueprintImplementableEvent/BlueprintNativeEvent - ✗Thinking Blueprint inheritance copies members instead of reusing the base
Follow-up questions
- →When do you choose
BlueprintNativeEventoverBlueprintImplementableEventfor a hook? - →How do you keep the C++/Blueprint split stable so reparenting later stays cheap?
MiddleTheoryCommonHow do you expose C++ systems to designers in Unreal Engine 5?
How do you expose C++ systems to designers in Unreal Engine 5?
Mark functions UFUNCTION(BlueprintCallable) and properties UPROPERTY(EditAnywhere). Add categories, tooltips, and clamps for discoverability, and expose BlueprintImplementableEvent hooks so designers extend C++ from Blueprint.
Common mistakes
- ✗Thinking any public C++ method is callable from Blueprint without
UFUNCTION - ✗Skipping categories and tooltips, leaving designers to guess what nodes do
- ✗Believing Blueprint cannot call native code, only read exposed values
Follow-up questions
- →When would you choose
BlueprintImplementableEventoverBlueprintNativeEvent? - →How do meta specifiers like
ClampMinorCategoryimprove the designer workflow?
MiddleTheoryCommonWhat are the risks of putting gameplay logic in the Level Blueprint?
What are the risks of putting gameplay logic in the Level Blueprint?
Level Blueprint logic cannot be reused across levels, is hard to diff and merge, and bloats one monolithic graph. It also creates hidden dependencies on specific level actors, so logic breaks silently when a level is duplicated or refactored.
Common mistakes
- ✗Assuming Level Blueprint logic is portable to other levels
- ✗Thinking one Level Blueprint is shared across all maps
- ✗Believing Level Blueprints are stripped from packaged builds
Follow-up questions
- →Where should level-specific scripting live instead of the Level Blueprint?
- →How does the Level Blueprint complicate version-control merges on a team?
MiddleTheoryOccasionalWhich gameplay logic should designers own versus programmers in UE5?
Which gameplay logic should designers own versus programmers in UE5?
Designers own tuning, content wiring, and fast-iterating gameplay feel in Blueprints. Programmers own core systems, performance-critical code, networking, and shared frameworks in C++, which exposes parameters and hooks for designers to drive.
Common mistakes
- ✗Letting designers own networking and core frameworks because Blueprint looks easier
- ✗Banning Blueprint gameplay entirely and treating all of it as tech debt
- ✗Assuming Blueprint and C++ are interchangeable for every gameplay task
Follow-up questions
- →How does this ownership split change the way you design a C++ API for designers?
- →What goes wrong when designers own replicated gameplay logic in Blueprint?
SeniorPerformanceOccasionalHow do you profile and cut Blueprint VM overhead when hundreds of actors tick?
How do you profile and cut Blueprint VM overhead when hundreds of actors tick?
Profile with stat game, Unreal Insights, and the Blueprint VM stat to find per-tick cost; each Blueprint node carries VM dispatch overhead. Move hot per-tick logic to C++, disable ActorTick where possible, batch updates, and replace tick loops with timers or events.
Common mistakes
- ✗Believing Blueprint nodes have zero runtime cost because the graph 'compiles'
- ✗Leaving
ActorTickenabled on every actor instead of using timers or events - ✗Profiling only the GPU frame and missing per-tick VM dispatch cost on the CPU
Follow-up questions
- →How do you decide which hot nodes to port to C++ versus restructuring the graph?
- →When does replacing a tick loop with a timer change gameplay behavior subtly?
SeniorDesignOccasionalOn a team where C++ engineers own base classes and designers build gameplay on top of them in the visual scripting system Blueprints, the engineers need to keep refactoring C++ internals while the designers' graphs must keep compiling. Designers reference C++ functions, properties, and class hierarchies by name from their graphs, and those references break silently when a name or signature changes or a class is reparented. Describe how you would design the C++/Blueprint boundary so internal refactors are safe. Requirements: the engine-exposed surface is treated as a stable contract; internal implementation can be reorganized freely without touching that surface; designers have sanctioned extension points to hook into; and renames or reparents are handled so existing designer graphs do not break.
On a team where C++ engineers own base classes and designers build gameplay on top of them in the visual scripting system Blueprints, the engineers need to keep refactoring C++ internals while the designers' graphs must keep compiling. Designers reference C++ functions, properties, and class hierarchies by name from their graphs, and those references break silently when a name or signature changes or a class is reparented. Describe how you would design the C++/Blueprint boundary so internal refactors are safe. Requirements: the engine-exposed surface is treated as a stable contract; internal implementation can be reorganized freely without touching that surface; designers have sanctioned extension points to hook into; and renames or reparents are handled so existing designer graphs do not break.
Treat the UFUNCTION/UPROPERTY surface as a contract: keep exposed signatures, names, and the class hierarchy stable, and refactor internals privately. Use BlueprintNativeEvent hooks and interfaces, version data carefully, and rename via Core Redirects so reparenting and renames don't break designer graphs.
Common mistakes
- ✗Treating exposed
UFUNCTION/UPROPERTYsignatures as freely refactorable internals - ✗Renaming or deleting exposed members without adding Core Redirects
- ✗Reparenting the C++ base class without checking what designer graphs depend on
Follow-up questions
- →How do Core Redirects let you rename an exposed function without breaking BPs?
- →When should the boundary be a
UInterfacerather than a base class?