You've got 200 items, each with a name, an icon, a price and a weight. Where do they live? Unreal gives you three answers — DataTable, DataAsset, Primary DataAsset — and beginners usually pick the first one they saw in a tutorial. Pick wrong and you find out around item 150, when the structure you chose fights everything you need. Let's get the choice right up front.
The three containers, in one line each
- DataTable — a spreadsheet. Many rows, all the same struct. Import from CSV/JSON.
- DataAsset — one custom asset instance. A rich, flexible structure. One per thing, or one config blob.
- Primary DataAsset — a DataAsset the Asset Manager can discover and load by ID at runtime, asynchronously.
DataTable: many rows, one shape
A DataTable holds rows that all share a single struct — ideal for "200 items, each with the same fields". You edit it like a spreadsheet, or import a CSV/JSON (last week's topic). Look up a row by name and you've got your data.
The catch: a DataTable is one asset, loaded whole. Every row loads together. And if a row holds a hard reference to a heavy mesh, loading the table drags in every mesh at once. (Yes — this is the soft reference trap wearing a different hat. Store soft references in your rows.)
Best when: lots of entries, identical shape, edited in bulk, and fine to have all in memory together.
DataAsset: one rich thing
A DataAsset is a single asset you fill with a custom structure — nested data, arrays, soft references, whatever your class declares. Instead of 200 rows in one file, you might make 200 separate assets, or a handful of config assets (one for the audio settings, one for the difficulty curve).
Because each is its own asset, you can soft-reference and load them individually — pull in this one weapon's data without touching the other 199. That's the structural difference from a DataTable that matters most.
Best when: entries have a rich or varying shape, or you want to load them one at a time.
Primary DataAsset: a DataAsset that scales
A PrimaryDataAsset is a DataAsset wired into the Asset Manager. You give it a type and an ID, and now the engine can enumerate "all weapons", load them asynchronously by ID, and keep them out of memory until something asks. This is what Lyra and most larger projects use for content catalogues.
The cost: you configure the Asset Manager (Project Settings → Asset Manager) and start thinking in Primary Asset IDs. More setup — but it's the only option here actually built for hundreds of individually-streamed assets.
Best when: a large, growing catalogue you want discoverable and async-loadable — every weapon, character or level in the game.
A quick decision
- Many identical entries, edit like a spreadsheet, fine to load together → DataTable.
- Rich or one-off config, load individually → DataAsset.
- Big catalogue, discover and async-load by ID → Primary DataAsset.
When you're torn between the last two, start with DataAsset — promoting to PrimaryDataAsset later is cheap. Going the other way, or migrating off a DataTable that outgrew its single struct, is the painful rewrite.
Plugin tip
Picking the container is half the job — filling it from real data is the other half. A designer hands you a CSV, an API returns JSON, and you need it inside a DataTable at runtime, not via an editor reimport.
FoxData bridges that gap: CSV/JSON into DataTable-shaped data at runtime, as Blueprint nodes. Optional, but it's what turns a "static table" into live, designer-editable data.Common pitfalls
- Hard references inside a DataTable. Loading the table loads every referenced asset. Use soft references in rows.
- DataTable for mismatched shapes. If entries need genuinely different fields, you'll fight the single-struct limit forever. That's DataAsset territory.
- Hand-rolling an asset registry. If you're building your own "find all X by tag" system, you're reinventing the Asset Manager — use PrimaryDataAsset instead.
- Editing a struct after you have rows. Changing the row struct can blank existing DataTable data. Decide the shape early; back up before big changes.
- Forgetting Asset Manager setup. PrimaryDataAssets won't be discoverable until you register their type in Project Settings.
The 30-second recap
- DataTable — many same-shaped rows, one asset, loaded whole. Spreadsheet data.
- DataAsset — one rich, custom asset; load it individually.
- Primary DataAsset — DataAsset + Asset Manager: discover and async-load by ID, at scale.
- Keep soft references in your rows so a table doesn't drag in every mesh.
- Unsure between DataAsset and PrimaryDataAsset? DataAsset now, promote when you need the catalogue.
Next up, votes permitting: A dialogue system that scales — from if/else hell to a data-driven setup with branching, conditions and localisation.
— Marco
Comments
Leave a comment