Potential bug related to UGameFeatureAction_DataRegistrySource?

I hit this issue when writing some experimental code and it may just be an unexpected coming together of settings. Similar to Lyra, all the settings in UDataRegistrySettings were left to default. This means an empty DirectoriesToScan and bInitializeAllLoadedRegistries is set to false.

Lyra only uses “Add Data Registry” which ends up calling UDataRegistrySubsystem::LoadRegistryPath which seems to work fine (it basically mutates AssetScanPaths which then makes RefreshRegistryMap behave as expected).

In my case I am manually loaded a data registry with the aim to then have a game feature plugin add a source to this. UGameFeatureAction_DataRegistrySource calls UDataRegistrySubsystem::PreregisterSpecificAssets which has an early out if IsConfigEnabled returns false. Because of the previous mentioned settings in UDataRegistrySettings, IsConfigEnabled will return false and thus my data source will never be scheduled to be added.

Now, this may be a case where I’m using the feature wrong (after all, my manual registry is not discoverable), but this feels a bit counterintuitive. Unless the expectation is that you set bInitializeAllLoadedRegistries to true if you are using game features, but that is not documented.

EDIT: thinking about it a bit more, due to how the data registry discovers assets, the only way to manually load and handle a data registry asset is likely in the same way game feature plugins register them (which means it gets added to the asset paths and this the registry refresh would handle it correctly).

Not in a position to test a repro right now for this, but I suspect if you use Lyra, and get a second game feature plugin to add a data source to the data registry that is added by ShooterCore it would likely fail due to the IsConfigEnabled check given Lyra’s ini configuration.

[Attachment Removed]

Hey there. You mention you are manually loading a Data Registry asset, to later have a GFP add a Data Table source to it. I see you’ve already studied both GFA_AddDataRegistry and GFA_AddDataRegistrySource.

I’ve just confirmed that even with the default project settings that make IsConfigEnabled() evaluate to true, activating two separate GFPs where:

  • GFP A adds a Data Registry with a DataTable Meta Source
  • GFP B adds the Data Registry Source, which ‘slots into’ the meta source

Then it doesn’t matter whether GFP A or GFP B is activated first, in both orders the data table will contribute to the data registry type. The RefreshRegistryMap function you mention is entered into in both orders of activation. My recommendation is to just follow what GFA_AddDataRegistry does, in terms of manually registering your Data Registry. Make sure it has a Data Table Meta Source entry since that is used to map the GFP’s source. I would call LoadRegistryPath.

Since you’re having trouble getting past the IsConfigEnabled() guard, you may want to defer some of your manual logic (like the manual Data Registry registration) to DataRegistrySubsystem->OnSubsystemInitialized(). IsConfigEnabled)() will then pass by virtue of bFullyInitialized == true.

You’ve probably encountered these callstacks, but just adding them for reference. This is when you have already added the Data Registry that expects meta sources, and activate the GFP with a Data Registry Source later. In your case, I expect that to process your already manually registered data registry.

>	UnrealEditor-DataRegistry.dll!UDataRegistrySubsystem::ApplyPreregisterMap(UDataRegistry * Registry) Line 730	C++
 	UnrealEditor-DataRegistry.dll!UDataRegistrySubsystem::PreregisterSpecificAssets(const TMap<FDataRegistryType,TArray<FSoftObjectPath,TSizedDefaultAllocator<32>>,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FDataRegistryType,TArray<FSoftObjectPath,TSizedDefaultAllocator<32>>,0>> & AssetMap, int AssetPriority) Line 713	C++
 	UnrealEditor-GameFeatures.dll!UGameFeatureAction_DataRegistrySource::OnGameFeatureActivating() Line 109	C++
 	UnrealEditor-GameFeatures.dll!UGameFeaturesSubsystem::OnGameFeatureActivating(const UGameFeatureData * GameFeatureData, const FString & PluginName, FGameFeatureActivatingContext & Context, const FGameFeaturePluginIdentifier & PluginIdentifier) Line 1326	C++

Alternatively, when registering the Data Registry Source first (while there is no DR yet), and the Data Registry later:

 	UnrealEditor-DataRegistry.dll!UDataRegistrySubsystem::ApplyPreregisterMap(UDataRegistry * Registry) Line 730	C++
 	UnrealEditor-DataRegistry.dll!UDataRegistrySubsystem::RefreshRegistryMap() Line 306	C++
>	UnrealEditor-DataRegistry.dll!UDataRegistrySubsystem::LoadRegistryPath(const FSoftObjectPath & RegistryAssetPath) Line 488	C++
 	UnrealEditor-GameFeatures.dll!UGameFeatureAction_DataRegistry::OnGameFeatureActivating() Line 84	C++
 	UnrealEditor-GameFeatures.dll!UGameFeaturesSubsystem::OnGameFeatureActivating(const UGameFeatureData * GameFeatureData, const FString & PluginName, FGameFeatureActivatingContext & Context, const FGameFeaturePluginIdentifier & PluginIdentifier) Line 1326	C++
 	UnrealEditor-GameFeatures.dll!FGameFeaturePluginState_Activating::UpdateState(FGameFeaturePluginStateStatus & StateStatus) Line 3941	C++

Hope that helps!

[Attachment Removed]