There is no correct ratio of Blueprint to C++. There is a defensible line, and being able to state yours is what matters.
Blueprints
Fast iteration and content
High-level gameplay flow
Level scripting and prototyping
UI logic and tuning
Anything a designer needs to touch
C++
Foundations and base classes
Hot paths and heavy math
Logic running every frame across many actors
Anything that benefits from code review
Anything needing clean source-control diffs
Blueprints hot-reload, they're visual, and they let designers self-serve without an engineering bottleneck. C++ runs at native speed and produces text you can diff, review, and refactor.
The deciding questions
Does it run per frame for many entities, or is it architecturally foundational? → C++.
Is it content, tuning, one-off gameplay flow, or something needing designer iteration? → Blueprint.
The mature pattern is both: the framework lives in C++, the knobs and composition live in Blueprints. Chapter 3 covers how to build that boundary deliberately.
2
The Downsides of All-Blueprint
Performance. Blueprint runs on an interpreted virtual machine, so per-node execution is far slower than native C++. Heavy per-tick logic across many actors is where this bites hardest — see Chapter 11 for the numbers.
Source control. Blueprints are binary .uasset files. You cannot diff or merge them meaningfully, so two people editing the same Blueprint means painful conflicts.
Maintainability. Large event graphs turn into spaghetti fast. They're hard to code review, hard to refactor, and hard to reason about at a glance.
Scale. As logic sprawls across dozens of Blueprints with hard references, load times and coupling grow and the architecture erodes. Chapter 7 covers why hard references are the specific mechanism.
The fix is not "avoid Blueprints" — it's keep them thin. Collapse logic into functions, push reusable or heavy work into C++ or function libraries, and decouple with interfaces and dispatchers.
3
Keeping a Large Blueprint Readable
Collapse to functions and macros with clear names and typed inputs and outputs, so the event graph reads like a table of contents rather than a wiring diagram.
Comment boxes and reroute nodes to group related logic and keep wires clean.
Break behavior into components and shared Blueprint Function Libraries, so logic is reused rather than copied.
Decouple with interfaces and event dispatchers instead of casting to concrete classes everywhere.
Hold conventions: consistent naming, variable categories, tooltips, and a shallow event graph that delegates to functions.
When a chunk gets heavy or is reused widely, promote it to a C++ base class.
Watch the function/macro distinction when you refactor: a macro containing a Delay compiles in an Event Graph but errors the moment it's dropped into a Function. Chapter 12 covers the rule.
4
Blueprint Interfaces
A Blueprint Interface is a set of function signatures with no implementation, which any number of unrelated classes can implement. It lets you call a function on an actor without knowing its exact class: you ask "does this thing implement Interactable?" and if so, call Interact().
It decouples the caller from the callee and avoids casting to specific classes — which avoids hard references and the loading they drag in.
Ideal for systems where many different actor types respond to the same message: interaction, "on focused", "can be targeted", generic reactions to a world event.
Interface vs. Cast
Cast To
Interface
Couples caller to
A specific class
A contract only
Adding new types
Requires modifying the caller
Zero caller changes
Reference cost
Hard reference to the class
No hard reference
Best for
Known, owned relationships
Open-ended systems
5
Communicating Between Blueprints
Three canonical methods, and the mental model for choosing between them.
Direct reference and cast. You hold a reference and call functions on it. Simple, but it creates a hard dependency and loads the referenced class. Fine when you legitimately have the reference — an actor talking to its own component, for instance.
Blueprint Interface. Call a function on something without knowing its concrete type. Best for "any actor might respond to this", and it avoids hard references.
Event Dispatcher. One-to-many broadcast. The sender fires an event and doesn't know or care who's listening. Best for "announce that something happened and let others react" — OnHealthDepleted, OnDoorOpened.
Rule of thumb. Known and owned → direct reference. Ask if you can → interface. Announce and let others react → dispatcher.
Prefer interfaces and dispatchers where you can. Hard references cause coupling and loading problems at scale, and both of these avoid them. Chapter 13 covers what an Event Dispatcher actually is underneath.
Interview drill
Answer each out loud before re-reading the chapter.
When do you reach for Blueprints versus C++? Where is the line for you?
What are the downsides of doing everything in Blueprints?
How do you keep a large Blueprint readable and maintainable?
What is a Blueprint Interface and when would you use one?
How do you communicate between Blueprints, and when does each method fit?