Data Tables vs Data Assets¶
When the same numbers are copied into ten Blueprint defaults, the problem is not a missing cast. The data has outgrown the actor that happens to use it.
The one-minute version¶
- A Data Table is many rows with the same struct shape. Use it when you want a spreadsheet-like list: level XP, item stats, enemy tuning rows, dialogue lines.
- A Data Asset is one authored asset object that holds data. Use it when each item/enemy/ability wants its own editable asset with references, inheritance, or designer-friendly grouping.
- Data Tables need a row struct. The row name is the stable key you use to find a row.
- Data Assets are assets, not spawned actors. Referencing a Data Asset gives you authored data, not a live world object.
- Move data out of Blueprint defaults when the same values must be shared, searched, tuned, localized, balanced, or reused by more than one class.
- Do not move everything into data on day one. Start when duplication or tuning pain is real.
The problem they solve¶
Blueprint class defaults are fine for one actor:
BP_BasicEnemy
MaxHealth = 50
WalkSpeed = 300
Damage = 10
They become painful when you have many entries:
BP_Slime, BP_Bat, BP_Golem, BP_Skeleton...
Each class has copied health, speed, XP, loot, icon, sound, and display name.
Now balancing the game means opening many Blueprints and hoping copied values stay consistent. Data Tables and Data Assets move those values into content assets that gameplay can read.
Data Tables¶
A Data Table is a list of rows. Every row has the same struct type.
Struct FEnemyTuningRow
DisplayName (Text)
MaxHealth (Float)
Damage (Float)
WalkSpeed (Float)
XPReward (Integer)
LootTableId (Name)
DataTable DT_EnemyTuning
RowName: Slime
RowName: Bat
RowName: Golem
Use a Data Table when:
- you have many entries with the same fields;
- designers want spreadsheet-style editing or CSV import/export;
- rows are looked up by stable row name;
- the data is mostly plain values and asset references;
- one graph can say "load row for this enemy ID."
The beginner rule: if you can imagine the data as rows and columns, a Data Table is probably a candidate.
Data Assets¶
A Data Asset is an asset instance that holds variables. Instead of one table with many rows, you make one asset per thing or per data package.
DA_FireballAbility
DisplayName = Fireball
Icon = T_FireballIcon
ManaCost = 25
Cooldown = 1.2
ImpactEffect = NS_FireImpact
DA_IceBoltAbility
DisplayName = Ice Bolt
Icon = T_IceIcon
ManaCost = 10
Cooldown = 0.6
ImpactEffect = NS_IceImpact
Use Data Assets when:
- each entry benefits from being its own asset in the Content Browser;
- entries need rich asset references such as meshes, sounds, materials, or Niagara systems;
- you want inheritance or data-only Blueprint variants;
- designers pick an asset reference directly on an actor/component;
- the data is more "one authored object" than "one spreadsheet row."
Data Assets are often easier for beginners because you can click an asset, edit named fields, and assign that asset to a Blueprint variable.
Row names and keys¶
Data Tables are only pleasant when row names are stable:
ItemId = Potion_Small
Get Data Table Row(DT_Items, RowName = ItemId)
Do not use display text as the row key. Display text can be localized, changed,
or made prettier. Use a stable Name, enum, or Gameplay Tag as the gameplay
identifier, then store display text as data.
Data Assets often use the asset reference itself as the ID:
CurrentAbilityData = DA_FireballAbility
That is clear for small projects. For larger projects, you may still give the asset an internal ID or use Primary Data Assets and the Asset Manager. That is past the month-one boundary, but the concept is the same: stable data identity separate from live actors.
When they fail¶
| Symptom | Likely cause | Fix shape |
|---|---|---|
| Data Table row lookup fails | Wrong row name, table not assigned, or struct mismatch. | Print row name, branch on success, and keep IDs stable. |
| Row fields are missing after struct change | The table was built from an older struct shape or needs reimport/review. | Update the struct/table together and inspect defaults. |
Data Asset reference is None |
The actor/component variable was never assigned. | Mark it instance editable or set a default asset on the class. |
| Changing data does not affect live actors | The actor copied values at BeginPlay and never reread them. | Decide whether data is read once or refreshed deliberately. |
| Multiplayer clients disagree | Only one machine changed local runtime state. | Replicate gameplay state; treat data assets/tables as shared definitions, not events. |
Failure should be explicit in your graph:
Get Data Table Row
-> Branch Row Found
true: apply row values
false: Print "Missing item row: ItemId"
What they do not do¶
- They do not spawn actors or widgets.
- They do not save player progress by themselves.
- They do not replace variables; they feed variables with better authored defaults or definitions.
- They do not make live object references durable across levels.
- They do not enforce balance rules. Your gameplay still decides how values are used.
- They do not replicate runtime changes. Data is definition; replicated state is still state.
The pattern everyone actually uses¶
For item pickup data:
Struct FItemRow
DisplayName
Icon
MaxStack
Weight
DT_Items:
Potion_Small
Key_Bronze
Ammo_Light
BP_Pickup:
ItemId = Potion_Small
BeginPlay or OnInteract:
-> Get Data Table Row DT_Items by ItemId
-> if found:
add item to inventory using row values
else:
print missing row
For abilities:
BP_AbilityComponent:
EquippedAbilities = Array of Ability Data Asset references
Input CastAbility
-> get selected ability data asset
-> read cost/cooldown/icon/effect class
-> run ability behavior owned by component/character
The data says what the ability is. The component or character still owns the runtime behavior.
Lookalikes - which one do I want?¶
| Tool | Use when | Watch out |
|---|---|---|
| Blueprint defaults | One class has simple values and no duplication pain yet. | Copying the same values into many classes gets stale. |
| Struct | Several fields should travel as one value. | It is not a database by itself. |
| Data Table | Many rows share one struct shape. | Row names and struct changes need care. |
| Data Asset | One authored asset should hold a reusable data package. | It is not a spawned actor. |
| SaveGame | Player progress must survive quitting. | SaveGame stores player data, not shared design definitions. |
| Game Instance | Runtime values must survive Open Level. | It is not persistent after quitting unless you save. |
Rule of thumb: table for many same-shaped rows, asset for one rich authored definition, SaveGame for player progress.
Going deeper¶
- Structs, Enums, and Switch on Enum - why Data Tables need a row struct.
- Arrays, Sets, Maps, and ForEach - storing row IDs, asset references, and lookup results.
- Blueprint variables and references - class, object, and asset references.
- Save Game: Create / Save / Load Game to Slot - player progress vs shared definitions.
- Official docs: Data Driven Gameplay Elements and Data Assets.
- Engine source (requires engine access - we do not reproduce it here):
UDataTableand row lookup helpers such asFindRowinEngine/Source/Runtime/Engine/Classes/Engine/DataTable.h;UDataAssetandUPrimaryDataAssetinEngine/Source/Runtime/Engine/Classes/Engine/DataAsset.h.