게임 엔진/Unreal

[Unreal] [Example] Editor에 Asset 생성 및 저장

AlgorFati 2021. 8. 10. 20:52

Create Asset to Editor

Unreal 에디터에 c++을 이용하여 원하는 에셋을 생성하는 예제이다.

 

 

Target Asset

Data Asset을 이용하기 위해서 먼저 사용하고자 하는 데이터 형태를 c++로 작성한다.

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "MyPrimaryDataAsset.generated.h"

UCLASS()
class TESTPROJECT_API UMyPrimaryDataAsset : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
	UPROPERTY(EditAnywhere)
		FString ItemName;

	UPROPERTY(EditAnywhere)
		UBlueprint* ItemBlueprint;

	UPROPERTY(EditAnywhere)
		FColor ItemColor;

	UPROPERTY(EditAnywhere)
		FVector Loc;

	UPROPERTY(EditAnywhere)
		FQuat Rot;
};

 

 

GameMode에서 에셋 생성

Header

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "TestProjectGameMode.generated.h"

UCLASS(minimalapi)
class ATestProjectGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	ATestProjectGameMode();

	virtual void StartPlay() override;
};

 

Source

#include "TestProjectGameMode.h"
#include "UObject/ConstructorHelpers.h"
#include "Engine/Engine.h"

#include "UnrealEd.h"
#include "UObject/Package.h"
#include "AssetRegistryModule.h"
#include "MyPrimaryDataAsset.h"

...

void ATestProjectGameMode::StartPlay()
{
	Super::StartPlay();

	FString AssetName = TEXT("MyPrimaryDataAsset");
	FString PackageName = TEXT("/Game/");
	PackageName += AssetName;

	UPackage* Package = CreatePackage(NULL, *PackageName);
	Package->FullyLoad();
	
	UMyPrimaryDataAsset* NewAsset = NewObject<UMyPrimaryDataAsset>(
		Package, *AssetName, RF_Public | RF_Standalone | RF_MarkAsRootSet);
	
	NewAsset->ItemName = TEXT("NewAssetName");

	Package->MarkPackageDirty();
	FAssetRegistryModule::AssetCreated(NewAsset);

	FString PackageFileName = FPackageName::LongPackageNameToFilename(
		PackageName, FPackageName::GetAssetPackageExtension());

	bool bSaved = UPackage::SavePackage(
		Package,
		NewAsset,
		EObjectFlags::RF_Public | EObjectFlags::RF_Standalone,
		*PackageFileName, 
		GError, nullptr, true, true, SAVE_NoError);

	TArray<UObject*> ObjectsToSync;
	ObjectsToSync.Add(NewAsset);
	GEditor->SyncBrowserToObjects(ObjectsToSync);

}

 

 

실행 결과

다음과 같이 에셋이 에디터에 저장된다.

 

 

 

Asset Load

모듈에서 Asset을 로드해야하는 경우가 생길 수 있다.

(로드 시 주의할 점은 Asset은 StartupModule 때 준비되지 않았을 수도 있다.)

FAssetRegistryModule& AssetRegistryModule =
		FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
FAssetData AssetData =
	AssetRegistryModule.Get().GetAssetByObjectPath(TEXT("/Game/MyPrimaryDataAsset.MyPrimaryDataAsset"));

if (AssetData.IsValid())
{
	UMyPrimaryDataAsset* Data = Cast<UMyPrimaryDataAsset> (AssetData.GetAsset());
	UE_LOG(LogTemp, Warning, TEXT("#######  Success %s #######"), *Data->ItemName);	
}
else
{
	UE_LOG(LogTemp, Warning, TEXT("#######  Failed  #######"));
}

 

 

Save Asset to Editor

언리얼 에디터에 새로운 에셋을 생성하여 저장할 수도 있겠지만, 기존에 있는 에셋의 데이터만 변경해야하는 상황도 충분히 생길 수 있다. 이런 경우 위 Create Asset to Editor 예제에서 일부 코드만 이용하여 구현할 수 있다.

 

Header

Header에서는 수정할 데이터 에셋을 Property로 갖고온다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "TestGameMode.generated.h"

class UTestPrimaryDataAsset;

UCLASS()
class ATestGameMode : public AGameModeBase
{
	GENERATED_BODY()
	
public:
	virtual void StartPlay() override;

private:
	UPROPERTY(EditAnywhere)
	UTestPrimaryDataAsset* DataAsset;
};

 

Source

#include "TestGameMode.h"
#include "UObject/ConstructorHelpers.h"
#include "Engine/Engine.h"
#include "UnrealEd.h"
#include "UObject/Package.h"
#include "AssetRegistryModule.h"
#include "TestPrimaryDataAsset.h"

void ATestGameMode::StartPlay()
{
	Super::StartPlay();

	DataAsset->Items.Add(TEXT("Test"));

	FString OutClassName;
	FString OutPackageName;
	FString OutObjectName;
	FString OutSubObjectName;
	FPackageName::SplitFullObjectPath(DataAsset->GetFullName(), OutClassName, OutPackageName, OutObjectName, OutSubObjectName);

	UE_LOG(LogTemp, Error, TEXT("OutClassName : %s  OutPackageName : %s  OutObjectName : %s  OutSubObjectName : %s"),
		*OutClassName,
		*OutPackageName,
		*OutObjectName,
		*OutSubObjectName);

	FString PackageName = OutPackageName;
	UPackage* Package = CreatePackage(NULL, *PackageName);
	Package->FullyLoad();

	Package->MarkPackageDirty();
	FAssetRegistryModule::AssetCreated(DataAsset);

	FString PackageFileName = FPackageName::LongPackageNameToFilename(
		PackageName, FPackageName::GetAssetPackageExtension());

	bool bSaved = UPackage::SavePackage(
		Package,
		DataAsset,
		EObjectFlags::RF_Public | EObjectFlags::RF_Standalone,
		*PackageFileName,
		GError, nullptr, true, true, SAVE_NoError);


	// 에셋의 수정 내용을 에디터에도 적용시켜준다.
	TArray<UObject*> ObjectsToSync;
	ObjectsToSync.Add(DataAsset);
	GEditor->SyncBrowserToObjects(ObjectsToSync);
}