A Thought Exercise: Breaking an Actor Blueprint Into Components
The theory is easy; the actual splitting is where you stall. Is this lump one card or three? This page operates on an enemy Blueprint everyone has written, breaks it down in four steps, and spells out the three principles — plus what "split too far" and "not split enough" each look like. This is a paper exercise: the goal is to build the instinct. Code is Lesson 27's job.
1. Today's Patient: BP_PatrolEnemy
The spec is standard — odds are you have written a near-identical one:
- Has a model and an idle animation, so it's visible;
- Walks back and forth along a string of patrol points;
- Switches to pursuit when the player comes within 800 units;
- Has 120 health, takes damage, dies at zero;
- Plays a VFX and a death scream when it dies;
- Drops one weapon and three coins on death;
- Has a health bar above its head;
- Respawns five seconds after dying.
In the Actor era all of that lives in one Blueprint — call it 400 nodes and 14 variables, extending some BP_CharacterBase. Let's take it apart.
2. Four Steps
Step one: translate the Blueprint into a list of verbs. Don't think about components yet; just ask what it does. One item per line, as fine-grained as you can manage — err on the side of too many here:
Show a model / play animation / move along a path / detect player distance / switch between patrol and pursuit / store health / take damage / determine death / play death VFX / play death audio / spawn loot / show a health bar / time a respawn.
Thirteen verbs. Notice that none of them is called "enemy" — "enemy" is a noun, and nouns belong to entities and prefabs, not to components.
Step two: group by "what changes together". This is the only step that requires real thought. The test isn't "do these feel similar", it's when a requirement changes, will these change together.
- "Store health / take damage / determine death" always change together → one card (health).
- "Move along a path / detect distance / switch patrol and pursuit" is one AI loop → one card (patrol AI). But note that "detect the player entering a radius" is something chests, traps and automatic doors all want; it will get reused on its own → pull that one out into its own card (proximity).
- "Play death VFX / play death audio" — a VFX and a sound are two kinds of asset, supplied by two kinds of component (particle system, sound), so they're already separate. What you actually have to write is "trigger them on death", and that belongs to an event raised by the health card.
- "Spawn loot" has nothing to do with health: chests drop things, quest rewards drop things → its own card (loot table).
- "Show a health bar" is presentation, not rules. The bar reads health, but health should not know the bar exists → its own card (health bar UI).
- "Time a respawn" is level pacing, unrelated to being an enemy; platforms and chests may want it → its own card (respawn).
Step three: decide what stays on the body and what sinks to a child entity. Only two rules, both from the main lesson: any part that needs to move independently gets its own entity, and one entity holds only one component of a given type. So: the weapon needs to swing on its own → child entity; the health bar floats above the head, following but not rotating with the body → child entity; the death VFX and scream are one particle and one sound, so they can stay on the body — but if you also want a hit-reaction VFX, that's two particle systems, and since only one of a type is allowed, you need another child entity.
Step four: write the checklist. Fully split, it looks like this:
P_PatrolEnemy entity (prefab root)
· mesh component the body model
· particle system component death VFX
· sound component death scream
· health_component ← custom: health, damage, death event
· patrol_ai_component ← custom: patrol points, pursuit, movement
· proximity_component ← custom: enter/leave radius → raise event
· loot_table_component ← custom: death event → spawn loot
· respawn_component ← custom: death event → timer → reset
│
├─ HealthBar entity (child: overhead bar)
│ · health bar UI component subscribes to health_component changes
│
└─ WeaponSocket entity (child: held weapon)
· mesh component weapon model
Five custom cards, plus four or five components supplied directly by assets. Compare that to the original 400-node Blueprint: same functionality, but now every boundary is written on the panel. And — health_component, loot_table_component and respawn_component work just as well on a chest. That's the whole payoff for splitting.
3. Three Principles for Splitting
Principle one: single responsibility — a card has exactly one reason to be edited. The test is crude but accurate: say out loud, "when would I edit this card?" If the answer contains the word "or", split it. "I'd edit it when tuning balance, or when art swaps the VFX" — two unrelated people editing the same card for two unrelated reasons means two cards.
Principle two: reusability — ask "could this go on a chest?" Best single question on this page. Pick each card up and imagine attaching it to something completely unrelated (a chest, a platform, a door). health_component on a chest? Sure — chests can be smashed. proximity_component on a door? Sure — that's an automatic door. patrol_ai_component on a chest? Not really — and that's fine, not every card has to be general. The point of the question is to surface the parts that could be general but got hardcoded into the enemy.
Principle three: data separated from behavior — one owner per piece of state. The health bar card doesn't store health; it reads the health from health_component. The loot card doesn't store "am I dead"; it subscribes to the death event. Give every piece of state exactly one owner and make everyone else a subscriber. Do that consistently and your dependency graph turns into a one-directional tree instead of a web of things tugging at each other.
Worth noting, Epic's best-practices page lands right on this: find the child components you need once on begin simulation, store the references or subscribe to their events, and react to events afterwards rather than rescanning the hierarchy during gameplay. That's both a performance note and an architectural one — it forces you to wire the relationship graph at startup instead of hunting for collaborators at runtime.
4. Split Too Far vs Not Split Enough
Both are traps, and they look nothing alike.
| Symptom | Consequence | Fix | |
|---|---|---|---|
| Not split enough | A card called enemy_component appears, 300 lines long, doing everything |
You renamed the God class into a file. None of composition's benefits, plus an extra layer of indirection | Say "when would I edit this", and cut wherever the answer contains "or" |
| Split too far | Health, max health, damage and death check become four cards; or a three-line set_visible_component shows up |
40 cards subscribing to each other, and who triggers whom is guesswork. One bug means jumping between five files | Merge back the cards that always change together |
Over-splitting has a great tell: two cards start relying on an implicit "must initialize in this order" agreement. If A only works after B, and that fact is written down nowhere, they were probably one card all along.
Under-splitting has a tell too: you see two unrelated groups of parameters in one card's @editable properties. "Patrol speed, number of patrol points" sitting next to "coins dropped, drop chance" on one panel means that card is serving two different people.
A closing note, unromantic but effective: split conservatively, then split again when it hurts. Cutting one card into two is ten minutes of work; gathering logic scattered across five cards back into one is usually half a day and easy to get wrong. Start at three-to-six custom cards. The second time you have to edit two cards for the same requirement, consider merging; the second time you want half of a card on some other object, consider cutting.
5. A Pocket Checklist
- Does the card's name contain a noun (door, enemy, chest)? → Probably split wrong; ability cards should be named after verbs or adjectives.
- Say "when would I edit this" — does the answer contain "or"? → Split.
- Could this card go on a chest? → "No" is fine, but check whether some part of it could be general and got hardcoded.
- How many cards write to the same piece of state? → More than one means pick an owner and turn the rest into subscribers.
- Are there two unrelated groups of parameters on one panel? → Split.
- Do two cards need a specific init order that's documented nowhere? → Merge.
- Is there a part that must move independently? → Give it its own child entity.
- Do you need two components of the same type? → Not allowed; split into a child entity.
6. Quick Quiz
While splitting the enemy you wrote one health_component that handles the health value, damage, the death check, playing the death VFX, and spawning loot. By this page's principles, what should change?
Sources
The framework rules cited here (how entities and components relate, the one-per-type limit, and the best practice of caching references on begin simulation) come from Epic's official documentation: Getting Started in Scene Graph in Fortnite (official docs) ↗ · Scene Graph Best Practices in Fortnite (official docs) ↗ · Components in Unreal Editor for Fortnite (official docs) ↗
health_component, patrol_ai_component and the rest of the checklist are invented names for this exercise, not official API; for the real built-in component types and their naming, defer to the official docs. The splitting principles are general software-design experience, not Epic statements.