LoginSignup
1
3

More than 1 year has passed since last update.

UE4,5 C++でData Assetを使う

Last updated at Posted at 2022-12-19

1. データモデルの作成

データ型の宣言(オプション)

DataManager.h
USTRUCT(BlueprintType)
struct FKawaiiStruct: public FTableRowBase
{
	GENERATED_BODY()

    // コンストラクタ
	FKawaiiStruct(){}
	FKawaiiStruct(const FName Name, const FSlateBrush Image): IconName(Name), IconImage(Image){}
	
    // 構造体構成値1:名前(FName)
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FName IconName;

    // 構造体構成値2:画像(FSlateBrush)
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FSlateBrush IconImage;
};

データアセットのデータ型の宣言

UPrimaryDataAssetを継承

DataManager.h
UCLASS(BlueprintType)
class UKawaiiAssetDataModel : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
    // 実際のデータ
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Data Setting")
	TArray<FKawaiiStruct> KawaiiData;
    
    // データ読み込み元(画像)のディレクトリ指定用
	UPROPERTY(EditAnywhere, Category="Data Setting", meta=(RelativeToGameContentDir))
	FDirectoryPath ImagePath;

    // データ取り込み用ファンクション
	UFUNCTION(CallInEditor)
	void LoadData();
};

データ読み込み用ファンクションの実装 (オプション)

DataManager.h
inline void UKawaiiAssetDataModel::LoadData()
{
    // 初期化
	KawaiiData.Empty();
    // 画像参照先パスの生成
	const FString Path = FPaths::Combine("/Game/", ImagePath.Path);
    // 指定ディレクトリ内アセットのリスト(パス名)の取得
	TArray<FString> Assets = UEditorAssetLibrary::ListAssets(Path, false);
	uint32 counter = 0;
	for(FString &Asset:Assets)
	{
        // パス名からアセットデータの取得
		FAssetData AssetData = UEditorAssetLibrary::FindAssetData(Asset);
		if(AssetData.AssetClass.ToString() == "Texture2D") // アセットがテクスチャの場合のみ処理
		{
			FSlateBrush IconImage;
			IconImage.ImageSize = FVector2d(100.f, 100.f); // サイズの指定
			IconImage.SetResourceObject(AssetData.GetAsset()); // 画像の指定
			KawaiiData.Add(FKawaiiStruct(AssetData.AssetName, IconImage)); // 配列に追加
			++counter;
		}
	}
    
	if(counter == 0) // 一つも処理できなかった場合(ディレクトリの指定エラー)
	{
		const FText Title = FText::FromString("Warning");
        // ダイアログの表示
		FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Select a Directory that has Images"), &Title);
	} else // 成功
	{
		FNotificationInfo NotifyInfo(FText::FromString(FString::FromInt(counter) + " Assets were Stored."));
		NotifyInfo.bUseLargeFont = true;
		NotifyInfo.FadeOutDuration = 7.f;
        // 処理数をNotificationに表示
		FSlateNotificationManager::Get().AddNotification(NotifyInfo);
	}
}

自動でデータを読み込むのは超便利

2. データアセットの作成

Content Browser右クリック > Miscellaneous > Data Asset

image.png

先ほど作ったデータアセットのデータ型(KawaiiAssetDataModel)を選択

image.png

データアセットが生成される

image.png

データセットにデータを読み込む

画像のあるディレクトリを指定して(1)、Load Data(2)でデータの読み込み ‐-今回の実装の場合

image.png

一瞬で読み込み完了

image.png

3. データアセットのデータを使う

データアセットへの参照

UseDataAsset.h

protected:
	// Asset Data(BP_KawaiiData_CPP)へのファイルパス
	UPROPERTY( EditAnywhere, meta = (AllowedClasses = "KawaiiAssetDataModel") )
	FSoftObjectPath KawaiiDataAssetPath;

private:

	UPROPERTY()
	TSoftObjectPtr<class UKawaiiAssetDataModel> KawaiiAssetData;

BP_ListView->Class Defaults->Details->Kawaii List View->Kawaii Data Asset Path

image.png

データアセットのデータを使う。今回の例だとアセットの配列からランダムに1データ取り出し返す。

UseDataAsset.cpp
	FKawaiiStruct KData;
	if(KawaiiAssetData == nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAssetPath: %s"), *KawaiiDataAssetPath.ToString());
		if(KawaiiDataAssetPath.IsNull()) return KData;
		KawaiiAssetData = Cast<UKawaiiAssetDataModel>(StaticLoadObject(UKawaiiAssetDataModel::StaticClass(), nullptr, *KawaiiDataAssetPath.ToString()));
		if(KawaiiAssetData == nullptr) return KData;
	}
	const int32 Max = KawaiiAssetData->KawaiiData.Num() - 1;
	KData = KawaiiAssetData->KawaiiData[FMath::RandRange(0, Max)];
	return  KData;

データアセットのプロパティとしてアクセスするだけなので超簡単。

コード全体

DataManager.h
#pragma once

#include "CoreMinimal.h"
#include "EditorAssetLibrary.h"
#include "Misc/MessageDialog.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"
#include "KawaiiDataManager.generated.h"


// Kawaii Structure
USTRUCT()	// BlueprintType
struct FKawaiiStruct //: public FTableRowBase <-for Datatable
{
	GENERATED_BODY()


public:
	FKawaiiStruct(){}
	FKawaiiStruct(const FName Name, const FSlateBrush Image): IconName(Name), IconImage(Image){}
	
	UPROPERTY(EditAnywhere)
	FName IconName;

	UPROPERTY(EditAnywhere)
	FSlateBrush IconImage;
};


// Kawaii Data Entry
UCLASS()	// Blueprintable
class LISTVIEW_CPP_API UKawaiiDataEntry : public UObject
{
	GENERATED_BODY()

public:

	UPROPERTY()	// BlueprintReadWrite
	FKawaiiStruct KawaiiData;
};

// Kawaii Data Asset Model
UCLASS()	// BlueprintType
class LISTVIEW_CPP_API UKawaiiAssetDataModel : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:

	UPROPERTY(EditAnywhere)	// EditAnywhere, BlueprintReadOnly, Category="Data Setting"
	TArray<FKawaiiStruct> KawaiiData;

	UPROPERTY(EditAnywhere, Category="Data Setting", meta=(RelativeToGameContentDir))
	FDirectoryPath ImagePath;

	UFUNCTION(CallInEditor)
	void LoadData();
};


// load asset into Asset Data 
inline void UKawaiiAssetDataModel::LoadData()
{
	KawaiiData.Empty();
	const FString Path = FPaths::Combine("/Game/", ImagePath.Path);
	TArray<FString> Assets = UEditorAssetLibrary::ListAssets(Path, false);
	uint32 counter = 0;
	for(FString &Asset:Assets)
	{
		FAssetData AssetData = UEditorAssetLibrary::FindAssetData(Asset);
		if(AssetData.AssetClass.ToString() == "Texture2D")
		{
			FSlateBrush IconImage;
			IconImage.ImageSize = FVector2d(100.f, 100.f);
			IconImage.SetResourceObject(AssetData.GetAsset());
			KawaiiData.Add(FKawaiiStruct(AssetData.AssetName, IconImage));
			++counter;
			UE_LOG(LogTemp, Warning, TEXT("Name: %s"), *AssetData.AssetClass.ToString());
		}
	}
	if(counter == 0)
	{
		const FText Title = FText::FromString("Warning");
		FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Select a Directory that has Images"), &Title);
	} else
	{
		FNotificationInfo NotifyInfo(FText::FromString(FString::FromInt(counter) + " Assets were Stored."));
		NotifyInfo.bUseLargeFont = true;
		NotifyInfo.FadeOutDuration = 7.f;
		FSlateNotificationManager::Get().AddNotification(NotifyInfo);
	}
}


KawaiiListView.h
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "KawaiiListView.generated.h"


UCLASS(Abstract)
class LISTVIEW_CPP_API UKawaiiListView : public UUserWidget
{
	GENERATED_BODY()

protected:

	UPROPERTY(meta=(BindWidget))
	class UListView *ListView;

	virtual void NativeConstruct() override;
	
	UPROPERTY( EditAnywhere, meta = (AllowedClasses = "KawaiiAssetDataModel") )
	FSoftObjectPath KawaiiDataAssetPath;
	
	UPROPERTY(EditAnywhere)
	int32 NumOfImage = 30;

private:

	UPROPERTY()
	TSoftObjectPtr<class UKawaiiAssetDataModel> KawaiiAssetData;

	struct FKawaiiStruct GetRandomDataFromAsset(); 

};


KawaiiListView.cpp
#include "KawaiiListView.h"
#include "KawaiiDataManager.h"
#include "Components/ListView.h"

void UKawaiiListView::NativeConstruct()
{
	Super::NativeConstruct();
	if(KawaiiAssetData) UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAsset is not null"));
	for(int i = 0; i < NumOfImage; i++)
	{
		UKawaiiDataEntry* Entry = NewObject<UKawaiiDataEntry>();
		Entry->KawaiiData = GetRandomDataFromAsset();
		ListView->AddItem(Entry);
	}
}


FKawaiiStruct UKawaiiListView::GetRandomDataFromAsset()
{
	FKawaiiStruct KData;
	if(KawaiiAssetData == nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAssetPath: %s"), *KawaiiDataAssetPath.ToString());
		if(KawaiiDataAssetPath.IsNull()) return KData;
		KawaiiAssetData = Cast<UKawaiiAssetDataModel>(StaticLoadObject(UKawaiiAssetDataModel::StaticClass(), nullptr, *KawaiiDataAssetPath.ToString()));
		if(KawaiiAssetData == nullptr) return KData;
	}
	const int32 Max = KawaiiAssetData->KawaiiData.Num() - 1;
	KData = KawaiiAssetData->KawaiiData[FMath::RandRange(0, Max)];
	return  KData;
}

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3