Data Asset Global Library

Hello, i recently learned about data assets and wanted to use them in my project.
I create a base “GameItem” in c++ according to the ActionRPG example as follows:

UCLASS(BlueprintType)
class GAMEPROTOTYPE_API UGameAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	UGameAsset() {}
	/** Type of this item, set in native parent class */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	FPrimaryAssetType Type;
	
	/** User-visible short name */
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FText Name;

	/** User-visible long description */
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FText Description;

	/** Icon to display */
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	UTexture2D* Icon;
	
	/** Returns the logical name, equivalent to the primary asset id */
	UFUNCTION(BlueprintCallable)
	FString GetIdentifierString() const;

	/** Overridden to use saved type */
	virtual FPrimaryAssetId GetPrimaryAssetId() const override;


	inline bool operator==(const UGameAsset& Other) const
	{
		return (GetPrimaryAssetId()==Other.GetPrimaryAssetId());
	}
};

After that, i created a derived asset as follows:

/** The base data structure of a skill */
UCLASS()
class GAMEPROTOTYPE_API UBaseSkillInfo : public UGameAsset
{
	GENERATED_BODY()
public :

	UBaseSkillInfo()
	{	
		Type = TEXT("Skill");
	} 

	/**
	* Comment
	*/
	AActor* Owner;

	/**
	* Comment
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	ESkillCastingMode CastingMode;

	/**
	* Ability to grant if this item is slotted
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TSubclassOf<class ABaseSkill> OfSkill;

	/**
	* Comment
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float Cost;

	/**
	* Comment
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float CooldownSeconds;

	/**
	* Comment
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float CastTime;
	
	/**
	* Comment
	*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	UParticleSystem* CastingParticle;

	/**
	* Animation wile casting
	*/
	UPROPERTY(EditDefaultsOnly)
	UAnimMontage* CastingAnimation;
};

In the editor i created several data assets that derive from this type, for example:

In the project settings i added the following to the asset manager:

I have to goal at this point:

  1. being able to access the “skill” data assets in c++

  2. being able to access the “skill” data assets in blueprints (by creating a global library in c++, or any other means)

i tried to use the UAssetManager examples and load primary assets by type, but its always returning nothing

what is the appropriate way to do this?

thank you!

Hello Kidakaka,

Have you looked at this tutorial for Asset management? Asset Management in Unreal Engine | Unreal Engine 5.1 Documentation

Thanks,

yes i did.
It didnt help me understand how to achieve my goals.

Hello Kidakaka,

I’m trying for something very similar. I would like to create asset bundles which you can optionally download into my game and load them once needed. So, they has to be stored in a standalone packages.

I still don’t know how to achieve my goal (same like you) but I found few more things you have not mentioned in your text:

At first, Unreal engine does have a tool called AssetAudit (Window / Development tools / AssetAudit). When your UPrimaryDataAsset based asset is correctly created and registered in ProjectSettings / AssetManager config, you should see your assets there:

For me, this works properly only when the asset class name (USFLPrimaryData in my case) correlates with the PrimaryAssetType field in the AssetManger definition. So I named it SFLPrimaryAsset there. In your case, you used (Skill vs UBaseSkillInfo). Does that work for you? maybe you need to rename “Skill” to “BaseSkillInfo”…

Another thing you have not mentioned in your text is the meta tag. Unreal ([according to the documentation][2]) uses the meta tag to specify the AssetBundle name. For example as follows:


/** The map that will be loaded when entering this zone */
UPROPERTY(EditDefaultsOnly, AssetRegistrySearchable, meta = (AssetBundles = "TestPkg"))
TAssetPtr TestMesh;

I’ve tagged the TestMesh property which is a member of my USFLPrimarytDataAsset class. The result is that both (the PrimaryDataAsset object and even the referenced TestMesh) are coocked into my game package (single file cooking) or chunk0 (chunked cooking) even when they are not referenced from any coocked map - but that’s all. I’ve expected Unreal will create TestPkg package for me but that did not happen.

Can anyone bring more light into this, please?
Kidakaka, have you managed to make any progress on this?

Hey, thanks for your reply, i really appreciate it
I managed doing something different for my needs, but i dont remember it completely ( i ended up removing this entirely through a better design)
I spent a lot of time stepping through the asset loading progress (while debugging) and i found something that worked…I kept some part of the code in case ill need it in the future, so ill post it at the bottom of this comment, mind its just a test.

I just tried what you suggested about the asset audit, i changed the name to BaseSkillInfo… no assets are showing in the window though.

I think that the idea of asset bundles is different than what i needed ( just reading all the files) so i never considered using it… but i will definitely use asset bundles in the future of this development, thank you!

Library.h:

UFUNCTION()
void OnRegistryLoaded();
UFUNCTION(BlueprintCallable
)
static TArray<class UBaseSkillInfo*> GetSkills();

Library.cpp:

ULibrary::ULibrary(const FObjectInitializer& Initializer) : Super(Initializer)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
	IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
	if (AssetRegistry.IsLoadingAssets()) {
		AssetRegistry.OnFilesLoaded().AddUObject(this, &ULibrary::OnRegistryLoaded);
	}
	else {
		OnRegistryLoaded();
	}
}

void ULibrary::OnRegistryLoaded()
{
	
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
	IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();

	TArray<FAssetData> AssetList;
	AssetRegistry.GetAssetsByClass(TEXT("BaseSkillInfo"), AssetList, true);



	for (const FAssetData& Asset : AssetList) {
		UObject* Obj = Asset.GetAsset();

		if (Obj->GetClass()->IsChildOf(UBaseSkillInfo::StaticClass())) {
			Skills.AddUnique(Cast<UBaseSkillInfo>(Obj));
		}

	}
}

TArray<class UBaseSkillInfo*> ULibrary::GetSkills()
{
	TArray<class UBaseSkillInfo*> Skills;
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
	IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();

	TArray<FAssetData> AssetList;
	AssetRegistry.GetAssetsByClass(TEXT("BaseSkillInfo"), AssetList, true);



	// Split assets into separate arrays.
	for (const FAssetData& Asset : AssetList) {
		UObject* Obj = Asset.GetAsset();

		if (Obj->GetClass()->IsChildOf(UBaseSkillInfo::StaticClass())) {
			Skills.AddUnique(Cast<UBaseSkillInfo>(Obj));
		}

	}
	return Skills;
}