Quick answer: Wait for the registry to finish loading by calling WaitForCompletion(), or subscribe to OnFilesLoaded. For shipping builds, ensure your cook included the directories you query and that the AssetRegistry.bin shipped. Use ScanPathsSynchronous for explicit paths.

Here is how to fix Unreal AssetRegistry queries that return zero results in your shipping build. You GetAssetsByClass for UMyDataAsset, expect 50 results, get 0. The cause is either the registry hasn’t finished loading at query time, or the cook excluded the assets entirely.

The Symptom

FAssetRegistryModule::Get().GetAssetsByClass returns empty array in shipping. Same code returns expected results in PIE. No errors logged.

What Causes This

Registry still loading. AssetRegistry loads asynchronously at startup. Querying before completion returns empty.

Cook exclusion. If a directory wasn’t in the cook list, its assets are absent from the shipped registry.

Wrong path search. Path-based searches use package paths, not file paths. /Game/Items works; Content/Items does not.

Class lookup ambiguity. Searching by class needs the class to be registered. UClass deferred loading can leave the class unregistered briefly at startup.

The Fix

Step 1: Wait for the registry.

FAssetRegistryModule& ARM = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AR = ARM.Get();

if (AR.IsLoadingAssets())
{
    AR.WaitForCompletion();
}

TArray<FAssetData> Assets;
AR.GetAssetsByClass(UMyDataAsset::StaticClass()->GetClassPathName(), Assets);
UE_LOG(LogTemp, Log, TEXT("Found %d assets"), Assets.Num());

Step 2: Subscribe to OnFilesLoaded for async use.

AR.OnFilesLoaded().AddLambda([&]()
{
    TArray<FAssetData> Assets;
    AR.GetAssetsByClass(UMyDataAsset::StaticClass()->GetClassPathName(), Assets);
    BuildItemList(Assets);
});

Avoids blocking the main thread on startup.

Step 3: Force-scan paths if not cooked.

TArray<FString> Paths;
Paths.Add("/Game/Items");
AR.ScanPathsSynchronous(Paths, true);
TArray<FAssetData> Items;
AR.GetAssetsByPath("/Game/Items", Items, true);

For DLC or mod content downloaded after launch, scan their paths first.

Step 4: Verify cook inclusion. Open Project Settings → Packaging → Additional Asset Directories To Cook. Add /Game/Items if your data lives there. Or register an Asset Manager Primary Type with that directory.

Step 5: Inspect the cooked registry. Use UnrealPak.exe -List to see what is in the .pak. Search for AssetRegistry.bin and the asset paths you expect.

Asset Manager Alternative

For typed game content (abilities, items, characters), Asset Manager is cleaner:

UAssetManager& AM = UAssetManager::Get();
TArray<FAssetData> AssetData;
AM.GetPrimaryAssetDataList(FPrimaryAssetType("Item"), AssetData);

Provides registry-level queries plus async loading helpers.

“Wait for the registry. Confirm cook inclusion. Use Asset Manager for typed data. Empty results turn into expected lists.”

Related Issues

For data asset cook reachability, see Data Asset Soft Refs. For DataTable lookup, see DataTable CSV.

WaitForCompletion. Cook the directory. Asset Manager for typed queries. Registry returns assets.