Games have far more content than fits in memory, so something must decide what to load, when, and when to free it. That's the Asset Manager.
Unreal does a lot of this automatically. The Asset Manager is for when you want explicit control, plus disk and memory auditing.
2
Primary vs. Secondary Assets
Primary Assets — the ones the Asset Manager knows by name and can load or unload on command. Each has a Primary Asset ID in the form Type:Name. By default, only levels are Primary. Promote something by overriding GetPrimaryAssetId.
Secondary Assets — everything a Primary Asset references: textures, meshes, materials. You don't load these by hand; they ride along when their Primary Asset loads.
A Primary Asset is a recipe you request by name. Secondary Assets are the ingredients that come along with it.
Two flavors of custom Primary Asset
Flavor
Use when
Trade-off
Blueprint class
You need to spawn instances, or want inheritance
More flexible, less memory-efficient
Data Asset
You just hold data
Simpler to access in code and lighter. It's an instance, which is why you can't inherit from it
The rule: need inheritance or spawning → Blueprint. Just storing data → Data Asset.
3
The Machinery
The Asset Manager is a singleton handling discovery and load decisions.
The actual async loading is done by a Streamable Manager inside it.
Streamable Handles are "someone still needs this" tickets. The asset stays resident while a handle exists; when nothing holds one, it becomes eligible for unload.
Loading uses reference counting — Load increments, Unload decrements — and the garbage collector reclaims the memory on its next pass once the count hits zero.
So "unload" releases a reference; it doesn't instantly free bytes. If you're watching a memory graph expecting an immediate drop, you won't see one until GC runs.
4
Asset Bundles
An Asset Bundle is a named subset of a Primary Asset's Secondary Assets that you can load as a group. It's built on soft references (TSoftObjectPtr) — paths that cost nothing until resolved (Chapter 7).
Define one statically with meta = (AssetBundles = "BundleName") on a soft-pointer property, or dynamically at runtime via FAssetBundleData.
UPrimaryDataAsset already implements the plumbing that scans soft pointers and keeps bundle data updated on save — which is why it's the recommended base.
Load functions take a list of bundle names, so you resolve only the slice you need. A lightweight Menu bundle and a heavier Game bundle can live on the same asset.
ChangeBundleStateForPrimaryAssets swaps which bundles are active on an already-loaded Primary Asset, without tearing it down.
5
Workflow
Optionally, register a custom Asset Manager via DefaultEngine.ini.
Register your Primary Assets — Project Settings → Asset Manager, pointing it at folders to scan, or in code.
Load and unload with LoadPrimaryAsset / UnloadPrimaryAsset, optionally specifying bundles.
Chapter 10 covers Game Features, which automate step 3 — you set a feature's state and it orchestrates the bundle loading for you, instead of scattering load calls through your code.