Primary data asset won't load no matter what I do?

Hey so I’ve been setting up primary data assets( to hold data tables and functionality to load them) but I’m running into the problem that for some reason the data assets won’t load, so far I’ve tried many different methods of asset loading but non have worked.

the below code is some of my failed attempts to get them to load(I have also tried using object finder but it always gives me the message that it can’t find the requested asset) any help that can be provided to help resolve my issue would be appreciated.

Attempt 1
UnrealGameInstance.h

UCLASS()
class UNREALCOC_API UUnrealGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:
	UUnrealAssetManager& UAM = UUnrealAssetManager::GetObj();

	FStreamableManager AssetLoader;

	UPROPERTY()
 	UPrimaryDataTableAsset* AssetDT = LoadObject<UDataTable_DataAsset>(NULL, TEXT("/Game/PrimaryAssets/DataTables/AssetDT.AssetDT"), NULL, LOAD_None, NULL);

	UUnrealGameInstance();

};

UnrealGameInstance.cpp

UUnrealGameInstance::UUnrealGameInstance() {
	
}

PrimaryDataTableAsset.h

UCLASS(Blueprintable)
class UNREALCOC_API UPrimaryDataTableAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AssetType")
	FPrimaryAssetType AssetType;

	//StreamHandle
	TSharedPtr<FStreamableHandle> Handle;

	TArray<FSoftObjectPath> Paths;

	FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &UPrimaryDataTableAsset::Del);

	virtual FPrimaryAssetId GetPrimaryAssetId() const override;

	UFUNCTION(BlueprintCallable, Category = "Name")
	FString GetIdentifierString() const;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DataTables")
	TArray<TSoftObjectPtr<UDataTable>> DataTables_Array;

	UFUNCTION(BlueprintCallable, Category = "Data Async Load Helper")
	void LoadSoftRef(UUnrealGameInstance* UGI);

	UFUNCTION(BlueprintCallable, Category = "Data Async Unload Helper")
	void UnloadSoftRef();

	UFUNCTION(BlueprintCallable, Category = "Delegate")
	void Del();

	UPrimaryDataTableAsset() {
		AssetType = UUnrealAssetManager::DTAssetType;
	}
};

PrimaryDataTableAsset.cpp

FString UPrimaryDataTableAsset::GetIdentifierString() const {
	return GetPrimaryAssetId().ToString();
}


FPrimaryAssetId UPrimaryDataTableAsset::GetPrimaryAssetId() const {
	return FPrimaryAssetId(AssetType, GetFName());
}


void UPrimaryDataTableAsset::LoadSoftRef(UUnrealGameInstance* UGI) {
	
	for (int32 Index = 0; DataTables_Array.Num() > Index; ++Index) {
		Paths.AddUnique(DataTables_Array[Index].ToSoftObjectPath());
	}

	if (this != nullptr) {
		Handle = UGI->AssetLoader.RequestAsyncLoad(Paths, Delegate);
	}
	
}


void UPrimaryDataTableAsset::UnloadSoftRef() {
	Handle.Get()->ReleaseHandle();

}


void UPrimaryDataTableAsset::Del() {
	while (!Handle.Get()->HasLoadCompleted()) {

	}
}

TestAppearance_Class.cpp

UCLASS(BlueprintType)
class UNREALCOC_API UTestAppearance_Class : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable)
	FString PlayerAppearanceCon(ACharacter* CPlayer, UGameInstance* GI);

};

TestAppearance_Class.cpp

FString UTestAppearance_Class::PlayerAppearanceCon(ACharacter* CPlayer, UGameInstance* GI) {
	APlayerCharacter_Class* Data_Player = Cast<APlayerCharacter_Class>(CPlayer);
	UUnrealGameInstance* Data_GI = Cast<UUnrealGameInstance>(GI);
	FString AppearanceDescription = "Place holder";

	if (Data_GI->AssetDT != nullptr){
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Working"));
		}
	}
	else {
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Not working"));
		}
	}

	return AppearanceDescription;
}

This attempt resulted in Not working being printed to the screen meaning AssetDT is equal to null, I don’t know why

Attempt 2
UnrealGameInstance.h

UCLASS()
class UNREALCOC_API UUnrealGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:
	UUnrealAssetManager& UAM = UUnrealAssetManager::GetObj();

	FStreamableManager AssetLoader;

	//StreamHandle
	TSharedPtr<FStreamableHandle> Prime_Handle;

	TSoftObjectPtr<UPrimaryDataTableAsset> SoftRef = TSoftObjectPtr<UPrimaryDataTableAsset>(FSoftObjectPath(TEXT("Blueprint'/Game/PrimaryAssets/DataTables/AssetDT.AssetDT")));
	

	void LoadFunc();

	void LoadCom();

	UUnrealGameInstance();

};

UnrealGameInstance.cpp

void UUnrealGameInstance::LoadFunc() {
	TArray<FPrimaryAssetId> ID_List;

	UAM.GetPrimaryAssetIdList(UUnrealAssetManager::DTAssetType, ID_List);
	
	if (ID_List.Num() > 0)
	{
		TArray<FName>Bundle;
		Prime_Handle = UAM.PreloadPrimaryAssets(ID_List, Bundle, false, FStreamableDelegate::CreateUObject(this, &UUnrealGameInstance::LoadCom));

	}
}

void UUnrealGameInstance::LoadCom() {
	while (!Prime_Handle->HasLoadCompleted())
	{
	
	}
}


UUnrealGameInstance::UUnrealGameInstance() {
	LoadFunc();
}

PrimaryDataTableAsset.h

UCLASS(Blueprintable)
class UNREALCOC_API UPrimaryDataTableAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AssetType")
	FPrimaryAssetType AssetType;

	//StreamHandle
	TSharedPtr<FStreamableHandle> Handle;

	TArray<FSoftObjectPath> Paths;

	FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &UPrimaryDataTableAsset::Del);

	virtual FPrimaryAssetId GetPrimaryAssetId() const override;

	UFUNCTION(BlueprintCallable, Category = "Name")
	FString GetIdentifierString() const;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DataTables")
	TArray<TSoftObjectPtr<UDataTable>> DataTables_Array;

	UFUNCTION(BlueprintCallable, Category = "Data Async Load Helper")
	void LoadSoftRef(UUnrealGameInstance* UGI);

	UFUNCTION(BlueprintCallable, Category = "Data Async Unload Helper")
	void UnloadSoftRef();

	UFUNCTION(BlueprintCallable, Category = "Delegate")
	void Del();

	UPrimaryDataTableAsset() {
		AssetType = UUnrealAssetManager::DTAssetType;
	}
};

PrimaryDataTableAsset.cpp

FString UPrimaryDataTableAsset::GetIdentifierString() const {
	return GetPrimaryAssetId().ToString();
}


FPrimaryAssetId UPrimaryDataTableAsset::GetPrimaryAssetId() const {
	return FPrimaryAssetId(AssetType, GetFName());
}


void UPrimaryDataTableAsset::LoadSoftRef(UUnrealGameInstance* UGI) {
	
	for (int32 Index = 0; DataTables_Array.Num() > Index; ++Index) {
		Paths.AddUnique(DataTables_Array[Index].ToSoftObjectPath());
	}

	if (this != nullptr) {
		Handle = UGI->AssetLoader.RequestAsyncLoad(Paths, Delegate);
	}
	
}


void UPrimaryDataTableAsset::UnloadSoftRef() {
	Handle.Get()->ReleaseHandle();

}


void UPrimaryDataTableAsset::Del() {
	while (!Handle.Get()->HasLoadCompleted()) {

	}
}

TestAppearance_Class.h

UCLASS(BlueprintType)
class UNREALCOC_API UTestAppearance_Class : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable)
	FString PlayerAppearanceCon(ACharacter* CPlayer, UGameInstance* GI);

};

TestAppearance_Class.cpp

FString UTestAppearance_Class::PlayerAppearanceCon(ACharacter* CPlayer, UGameInstance* GI) {
	APlayerCharacter_Class* Data_Player = Cast<APlayerCharacter_Class>(CPlayer);
	UUnrealGameInstance* Data_GI = Cast<UUnrealGameInstance>(GI);
	FString AppearanceDescription = "Place holder";

	if (!Data_GI->SoftRef.IsNull()){
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Working"));
		}
		
		if (Data_GI->SoftRef.IsValid())
		{
			if (GEngine) {
				GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Working2"));
			}
		}
		else {
			if (GEngine) {
				GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Not working 2"));
			}
		}
		
	}
	else {
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Not working"));
		}
	}

	return AppearanceDescription;
}

In this attempt IsNull returns false (Which becomes true due to not) printing Working, but on IsVaild it returns false printing Not working, so esse

Firstly, I don’t know how safe that is to call in the header.

Two things:

  • Make sure you have the PrimaryAssetType + directory path set up in ProjectSettings->AssetManagement
  • Do not tick the “HasBlueprintClasses” if your DataAssets are from c++, as it actually means “IsBlueprintClass”, and will only seek blueprint derived DataAssets

The PrimaryAssetType you fill in the project settings has to equal the one set on your asset. In the settings: “EventAsset”, and in my asset class:

 UEventAsset::PrimaryAssetType() { return FPrimaryAssetId("EventAsset", GetFName()); }

This is how I get my PrimaryDataAssets:

	template<class T>
	/// Will retrieve PurposeAssets, determined by type T
	/// @param T: A PurposeAsset class which has a static method PrimaryAssetType(), which will determine which PurposeAssets are retrieved
	static TArray<TSoftObjectPtr<T>> GetAssets()
	{
		UPurposeAssetManager& assetManager = UPurposeAssetManager::AssetManager();

		TArray<FAssetData> assets;
		assetManager.GetPrimaryAssetDataList(T::PrimaryAssetType(), assets);
		TArray<TSoftObjectPtr<T>> purposes;

		for (FAssetData& asset : assets)
		{
			purposes.Add(Cast<T>(asset.GetAsset()));
		}

		return purposes;
	}

3 Likes

Thank you so much!
The wording of the “HasBlueprintClasses” comment made it sounds like I have to toggle it on if my data asset is a blueprint class (which is actually a child class of my custom c++ asset type)

Disable the flag and my async loading code works! :smiley:

2 Likes

Thanks! This helped me too after spending many hours trying to figure out why assets were not loading!