Data Assets not fully loaded when loaded from FGameFeaturePluginState_Loading

I’m using a typical game feature policy to pre-load plugin assets on boot.

UGameFeaturesSubsystem::Get().LoadBuiltInGameFeaturePlugins( AdditionalFilter, FBuiltInGameFeaturePluginsLoaded::CreateUObject(this, &UMyGameFeaturePolicy::OnBuiltInGameFeaturePluginsLoaded) ); Is called in InitGameFeatureManager

Is called in InitGameFeatureManager.

GetPreloadAssetListForGameFeature

The above is gathering the assets I expect.

I’m seeing a correct filter when loading to force sync:

OutOptions.bForceSyncLoading = true;

I’m calling DumpLoadedAssetState within my OnBuiltInGameFeaturePluginsLoaded.

All assets I expect show up in the list, but some are pending.

I would have expected the bundle handle in the Loading Plugin state WaitUntilComplete would not move forward until all parts of the asset (including the soft object bundles) are loaded.

Is this an incorrect assumption?

Hey Daniel, since this question has been lingering unanswered for a while I’m investigating this, but since this part of the engine code is out of my wheelhouse I’ll primarily gather more info before consulting my colleagues.

Looking at FGameFeaturePluginState_Loading::UpdateState() I would expect the plugin’s state to only transition to Loaded if:

  • All initially requested assets are loaded, whether that’s synchronously via that blocking load or async due to returning.
  • Or, if BundleHandle somehow got nulled in the meantime

Since you’re running into behavior you didn’t expect, would it be possible for you to add some debugging code?

  • In FGameFeaturePluginState_Loading::BeginState() it would be useful to debug log all requested primary asset paths, BundleHandle->GetRequestedAssets(), right before BindCompleteHandle()
  • In FGameFeaturePluginState_Loading::UpdateState() right before SetTransition(Loaded):
    • It would be useful to log whether BundleHandle is still valid, and if so to log out GetRequestedAssets() and GetLoadedAssets().
    • A call to DumpLoadedAssetState there would be useful too.

Can you report back with that info? I understand if you’d want to anonymize the asset names.

The assets that hadn’t finished loading, are they ones you directly returned in your policy’s GetPreloadAssetListForGameFeature()? If so, are they also included in BundleHandle->GetRequestdAssets() when you log them out in BeginState?

Hey again, I would like to confirm something with you: although DumpLoadedAssetState() prints that some of those assets are ‘pending load’, what happens when you are trying to access those assets immediately? I believe the issue might be just a misreporting of DumpLoadedAssetState. I’ve set up a repro project and found that bundle assets that should be loaded appear in BundleHandle->ChildHandles.

However, when I try to access the request objects I can resolve them as full UObjects. Example engine modification:

`virtual void UpdateState(FGameFeaturePluginStateStatus& StateStatus) override
{
TRACE_CPUPROFILER_EVENT_SCOPE(GFP_Loading_Update);
check(StateProperties.GameFeatureData);

if (BundleHandle)
{
if (!UseAsyncLoading())
{
BundleHandle->WaitUntilComplete(0.0f, false);
}

if (BundleHandle->IsLoadingInProgress())
{
return;
}

// START MODIFICATION
TArray RequestedAssets;
BundleHandle->GetRequestedAssets(RequestedAssets, true);
for (const FSoftObjectPath& Path : RequestedAssets)
{
if (UObject* Obj = Path.ResolveObject())
{
UE_LOG(LogTemp, Warning, TEXT(“Requested asset was loaded: %s”), *Obj->GetPathName());
}
else
{
UE_LOG(LogTemp, Warning, TEXT(“Requested asset was NOT loaded: %s”), *Path.ToString());
}
}

UAssetManager::DumpLoadedAssetState();
// END MODIFICATION

if (BundleHandle->WasCanceled())
{
BundleHandle.Reset();
StateStatus.SetTransitionError(EGameFeaturePluginState::ErrorLoading, GetErrorResult(TEXT(“Load_Cancelled_Preload”)));
return;
}
}`And console output:

LogTemp: Warning: Primary asset id: MyDataAsset:MDA_MyDataAsset LogTemp: Warning: Requested asset was loaded: /PluginTagTest/DataAssets/MDA_MyDataAsset.MDA_MyDataAsset LogTemp: Warning: Requested asset was loaded: /PluginTagTest/BP_MyActorClass.BP_MyActorClass_C LogTemp: Warning: Requested asset was loaded: /PluginTagTest/PluginTagTest.PluginTagTest LogAssetManager: =========== Asset Manager Loaded Asset State =========== LogAssetManager: Type GameFeatureData: LogAssetManager: PluginTagTest: loaded, (Client, Core, Server) LogAssetManager: Type MyDataAsset: LogAssetManager: MDA_MyDataAsset: pending load, (Client, Core, Server)Here I see that MDA_MyDataAsset is already resolvable yet reported as pending load. In your project, are the reported pending load objects actually still loading?

Edit: I realize that in your case its not about the data asset itself, but the asset soft reference inside the data asset. But my logs already show that DumpLoadedAssetState can misreport the pending load state, so I’m curious if those soft referenced assets in requested bundles are loaded or not.

Responding again: I realized my tests so far have been in a more recent engine version and that may affect my results compared to yours in 5.4. When you have time to debug again, can you also check at the moment BundleHandle->IsLoadingInProgress() returns false, whether:

  • Do the soft referenced bundle assets appear in BundleHandle->ChildHandles?
  • Is bLoadCompleted true on all those ChildHandles?

Here’s an example:

`[2025.04.24-16.53.57:101][ 0]LogGameFeatures: Warning: Printing PreLoading asset list in Game feature Core_Progression

[2025.04.24-16.53.57:102][ 0]LogGameFeatures: Warning: PreLoading asset ProgressionDefinition:Progression.Key.S.P

[2025.04.24-16.53.57:102][ 0]LogGameFeatures: Warning: PreLoading asset ProgressionDefinition:Progression.Key.S.D

[2025.04.24-16.53.57:102][ 0]LogGameFeatures: Warning: PreLoading asset ItemDefinition:Item.C.R

[2025.04.24-16.53.57:102][ 0]LogGameFeatures: Warning: PreLoading asset ItemDefinition:Item.C.G

[2025.04.24-16.53.57:102][ 0]LogGameFeatures: Warning: PreLoading asset GameFeatureData:Core_Progression

[2025.04.24-16.53.57:107][ 0]LogGameFeatures: Warning: FGameFeaturePluginState_Loading About to transition to Loaded for Game Feature Core_Progression

[2025.04.24-16.54.02:196][ 0]LogGameFeatures: Warning: BundleHandle still valid when setting transition to loaded for Core_Progression, Loading In Progress 0, UseAsyncLoading: 0

[2025.04.24-16.54.02:953][ 0]LogGameFeatures: Warning: Calling DumpLoadedAssetState before SetTransition loaded for Core_Progression

[2025.04.24-16.54.03:418][ 0]LogAssetManager: =========== Asset Manager Loaded Asset State ===========

[2025.04.24-16.54.03:419][ 0]LogAssetManager: Type GameFeatureData:

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Core_CombatStats: loaded, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Core_GameLoop: loaded, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Core_Mastery: loaded, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Core_Progression: loaded, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Type ItemDefinition:

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Item.C.G: pending load, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Item.C.R: pending load, (Core)

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Type ProgressionDefinition:

[2025.04.24-16.54.03:420][ 0]LogAssetManager: Progression.Key.S.D: pending load, (Core)

[2025.04.24-16.54.03:421][ 0]LogAssetManager: Progression.Key.S.P: pending load, (Core)`

For an example of the Core bundle. The item definition has this property:

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = “Inventory”, meta = (AssetBundles = “Core”))

TSoftClassPtr<AMKTItem> Item;