How to update references/dependencies automatically at build/cook?

In my project I have an AActor type that needs to reference many UDataAssets. You can imagine this as a character with a list of abilities or equipment items, etc. The naive solution is simply a large TArray. However, this becomes cumbersome over time as anyone on the team adding or removing from this list has to check out the owning AActor BPs. You also run into issues with inheritance and juggling changing list indices, repeated work of updating assets, or dealing with the headache of gameplay needs diverging from the inheritance hierarchy. It creates contention on the collection assets and arguably muddies their revision history.

I’d like to take a more data driven approach where each UDataAsset and consumer AActor has a tag container, and I use that to determine which UDataAssets the AActors need. I can get this working by querying the AssetRegistry in the PostLoad() to search for the data assets.

My main issue is I’m not sure when in the asset lifecycle I should update these properties such that the cooking and dependency tracking works properly.

When I update my actors in PostLoad I see these warnings during cook when it determines my actors are suddenly pointing to my data assets:

This is a hidden dependency, causes poor cook performance, and it might be a bug to add it to the cook. Declare this package in the AssetRegistry dependencies of the loading package, or mark up its load with FCookLoadScope to specify whether it is runtime or editoronly.

I’m not sure how to resolve this properly. How can I “Declare this package in the AssetRegistry dependencies of the loading package”?

Some other thoughts:

I’m also worried about Incremental Cooks. If the tags are changed on a data asset, I’ll need some way to re-cook the target assets. Maybe I can just do this in UAssetManager::ModifyCook?

Is cook time even the right place to be doing this? Is there some other kind of derived data functionality I should look into?

Should I abandon trying to “bake” the UDataAsset list and simply query the AssetRegistry in BeginPlay()? That seems somewhat wasteful as these lists are set at build time but perhaps the AssetRegistry is plenty fast?

Is this the right direction or should I try something else entirely?

Hi there,

Have you explored the Gameplay Ability System, it may contain the features you are looking for with all of the pain points already managed.

Another approach utilizing the AssetRegistry may be to create an EditorUtilty that updates a TMap of “Tag” to “Ability” mappings ( or some other data structure ) during editor time.

[Image Removed]

`class AAbilityFactory;

/**
*
*/
UCLASS(Blueprintable)
class CASE20014246_API UAbilityFactoryActionUtility : public UActorActionUtility
{
GENERATED_BODY()

public:

UFUNCTION(BlueprintCallable)
void BuildAbilityMapFromDataAssetsInContentBrowser(AAbilityFactory *AbilityFactory);

};

void UAbilityFactoryActionUtility::BuildAbilityMapFromDataAssetsInContentBrowser(AAbilityFactory* AbilityFactory) {

FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(“AssetRegistry”);
TArray AssetData;

const UClass* Class = UDataAsset::StaticClass();
AssetRegistryModule.Get().GetAssetsByClass(Class->GetClassPathName(), AssetData);

AbilityFactory->UpdateAbilitiesFromDataAssets(AssetData);

}`

then you can retrieve the attributes during runtime ( or editor time ) through the AbilityFactory and apply them.

`TArray AAbilityFactory::GetAbilitiesWithTag(TArray Tags) {

//TODO return abilities from TMap

}`

This may manage the unruly nature of manually curating the DataAssets and still preserves the intended cook/build/package behavior.

Thank you for the reply. Yes, this is actually about organizing UGameplayAbility references across our character types.

I can move to simply compiling the list in BeginPlay() if automatically storing it at editor time isn’t feasible. Thanks!