Content pipeline¶
How content gets from designer brain to running game. Two halves: data assets (already authored), and the Blueprint authoring layer (in progress) that lets new verbs ship without C++.
Data assets¶
The shipping content layer. See Data assets for the conceptual intro and Authoring/RuneAuthoring for designer instructions.
Two classes today:
URuneDataAsset¶
One asset per rune word. Defines:
- Display:
RuneWord,EnglishDefinition,RuneVisualMesh. WordType(NOUN or VERB) drives editor field visibility.- Noun fields:
NounMesh,NounMaterials,bNounSimulatesPhysics,InherentEffectComponents,VerbComponentOverrides. - Verb fields:
TwoWordEffectComponent,ThreeWordEffectComponent. - Split:
bIsSplittable,RuneSplitData. - Audio:
PickupSound,PlaceSound,SplitSound,ActivationSound.
Field visibility uses meta = (EditCondition = "WordType == EWordType::NOUN", EditConditionHides) so the inspector hides irrelevant fields based on word type. Designers see only what applies.
Convention: assets live under Content/Runes/ and are named DA_Rune_<WORD> (e.g. DA_Rune_TREE, DA_Rune_FLOAT).
UMergeRecipeDataAsset¶
For combine slots. Holds a TArray<FMergeRecipe>:
InputRunes order doesn't matter — the combine slot does set-membership matching. Multiple recipes per asset is fine; the combine slot iterates and fires the first match.
Convention: Content/Recipes/, DA_MergeRecipe_<purpose>.
Blueprint authoring layer¶
The "Blueprint engineer / tech designer" workflow exists to keep the rune system designer-extensible without forcing C++ for every new verb. Status today:
| Authoring path | Status |
|---|---|
| New rune word (data asset) | shipped |
| New merge recipe (data asset) | shipped |
| New noun (mesh + materials + inherent components) | shipped — author the rune's data asset, optionally Blueprint-subclass the inherent component |
| New runeable object subclass | shipped — Blueprint-subclass ARuneableObject |
| New slot variant | shipped — Blueprint-subclass ARuneSlot (or one of the existing subclasses) |
| New verb effect component | partial — Blueprint can subclass URuneEffectComponent for tuning, but tick logic still requires C++ |
| New strategy | not authorable in BP — strategies are stateless C++ |
The "partial" entry is the live project. URuneEffectComponent is Blueprintable and OnEffectApplied / OnEffectRemoved are BlueprintNativeEvent, so a designer-friendly verb whose only behavior is "spawn this Niagara, wait N seconds, undo" is buildable today in BP. Anything that ticks or interacts with physics still needs a C++ subclass first.
Roadmap: a small Blueprint base class per "verb category" (modifier, bidirectional, hazard) will be added so 80% of new verbs can ship without engine code. Tracked under Plan/DevelopmentPlan.
Asset naming and folder layout¶
The structure that's settled in:
Content/
Blueprints/
BP_RephraseCharacter
BP_RuneCalculator subclass per puzzle archetype
BP_FireComponent subclass with project's Niagara assigned
BP_ClockDevice
...
Runes/
Nouns/
DA_Rune_TREE
DA_Rune_ROCK
DA_Rune_CAMPFIRE
...
Verbs/
DA_Rune_FLOAT
DA_Rune_ROTATE
DA_Rune_IS
...
Recipes/
DA_MergeRecipe_*
Input/
IMC_Default
IA_Move, IA_Interact, ...
Levels/
Rune Showcase
L_Demo_*
VFX/
NS_Fire, NS_Discovery, NS_RingExpanding, ...
Materials/
M_*
UI/
WBP_HUD, WBP_RuneDefinition, ...
The exact paths float as content gets reorganized; this is the rough shape. Engineers should not be moving content folders around — coordinate with the tech designer / engineering producer.
How a designer ships a new rune¶
- Right-click in
Content/Runes/Nouns/(orVerbs/) → Miscellaneous → Data Asset →RuneDataAsset. - Name it
DA_Rune_<WORD>. - Open the asset, fill in
RuneWord,EnglishDefinition,RuneVisualMesh,WordType. - Fill in word-type-specific fields (mesh + materials for noun; effect components for verb).
- Add to a slot's
bSpawnWithInitialRuneconfig or a memory palace assignment. The rune is now in-game.
No C++ rebuild. No engineer involvement unless a new verb effect component is needed.
Build and module dependencies¶
Source/Rephrased_Demo/Rephrased_Demo.Build.cs declares everything the runtime module needs:
- Public:
Core,CoreUObject,Engine,InputCore,UMG,Niagara,EnhancedInput. - Private:
Slate,SlateCore.
UMG and Slate/SlateCore for the HUD and definition widgets. Niagara for fire, ring propagation, and discovery VFX. EnhancedInput for the input mapping context. New engine modules go in PublicDependencyModuleNames; rebuild the project after editing.
.uproject plugins¶
Currently enabled in Rephrased_Demo.uproject:
ModelingToolsEditorMode— editor-only blockout.GameplayStateTree— reserved for future NPC scripting; not active.Aura— disabled.
No third-party plugins in tree. Audio path will introduce the FMOD plugin when it ships (see Audio).
Source files¶
Source/Rephrased_Demo/RuneDataAsset.hSource/Rephrased_Demo/MergeRecipeDataAsset.hSource/Rephrased_Demo/Rephrased_Demo.Build.csRephrased_Demo.uproject
Known constraints¶
- No data validation pass. A noun with a null
NounMeshor a verb with both effect-component fields null and a non-IS intent both ship as "broken" without compile-time warning. Adding asset validators is on the post-Gate-2 polish list. - Recipe matching is set-equality. Duplicate-input recipes (e.g. "two TREEs make one BIGTREE") need an extra
int32count field onFMergeRecipe::InputRunes— not currently supported. Content/reorganizations break references; the asset registry usually fixes them but full-content moves should still go through the tech designer.
Change history¶
- 2026-05-23 — Gabriel Li — Default engineer sandbox: Rune Showcase (replaces L_Sandbox in tree example).
- 2026-05-08 — Gabriel Li — Added baseline change history section for weekly wiki maintenance.