1. ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ํจํค์ง
- ๋จ์ผ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๊ฐ ๊ฐ์ง ์ ๋ณด๋ ์ ์ฅํ ์ ์์ง๋ง, ์ค๋ธ์ ํธ๋ค์ด ์กฐํฉ๋์ด ์๋ค๋ฉด?
- ์ ์ฅ๋ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฐพ๊ณ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์?
- ๋ณต์กํ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ ์ฅ๊ณผ ๋ถ๋ฌ๋ค์ด๋ ๋ฐฉ๋ฒ์ ํต์ผํด์ผ ํ๋ค.
- ์ธ๋ฆฌ์ผ ์์ง์ ์ด๋ฅผ ์ํด ํจํค์ง(UPackage) ๋จ์๋ก ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ฅผ ๊ด๋ฆฌํจ
- ํจํค์ง์ ์ค์์ ๊ฐ๋
- ์ธ๋ฆฌ์ผ ์์ง์ ๋ค์ํ ๊ณณ์์ ๋จ์ด ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ณ ์์
- ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ฅผ ๊ฐ์ผ ํฌ์ฅ ์ค๋ธ์ ํธ๋ฅผ ์๋ฏธํจ ๐ ํฌ์คํ ์ ์ฃผ์
- ๋ํ ๊ฐ๋ฐ๋ ์ต์ข ์ฝํ ์ธ ๋ฅผ ์ ๋ฆฌํด ํ๋ก๊ทธ๋จ์ผ๋ก ๋ง๋๋ ์์ ์ ์๋ฏธํจ ์) ๊ฒ์ ํจํค์ง
- DLC์ ๊ฐ์ด ํฅํ ํ์ฅ ์ฝํ ์ธ ์ ์ฌ์ฉ๋๋ ๋ณ๋์ ๋ฐ์ดํฐ ๋ฌถ์์ ์๋ฏธํ๊ธฐ๋ ํจ ์) pkg ํ์ผ
- ๊ตฌ๋ถ์ ์ํด ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ํจํค์ง๋ก ๋ถ๋ฅด๋ ๊ฒ๋ ๊ณ ๋ คํ๋ค.
๐ฉ ํจํค์ง์ ์์
- ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ํจํค์ง๋ ๋ค์์ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ฅผ ํฌ์ฅํ๋๋ฐ ์ฌ์ฉํ๋ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ
- ๋ชจ๋ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ ํจํค์ง์ ์์๋์ด ์์ ์) Transient Package
- ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ํจํค์ง์ ์๋ธ ์ค๋ธ์ ํธ๋ฅผ ์์ (asset)์ด๋ผ๊ณ ํ๋ฉฐ ์๋ํฐ์๋ ์ด๋ค์ด ๋ ธ์ถ๋จ
- ๊ตฌ์กฐ์ ํจํค์ง๋ ๋ค์์ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ๋ฅผ ์์ ํ ์ ์์ผ๋, ์ผ๋ฐ์ ์ผ๋ก๋ ํ๋์ ์์ ๋ง ๊ฐ์ง
- ์์
์ ๋ค์์ ์๋ธ ์ค๋ธ์ ํธ๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ๋ชจ๋ ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ํจํค์ง์ ํฌํจ๋จ
- ํ์ง๋ง ์๋ํฐ์๋ ๋ ธ์ถ๋์ง ์์
2. ์์ ์ ๋ณด์ ์ ์ฅ๊ณผ ๋ก๋ฉ ์ ๋ต
- ๊ฒ์ ์ ์ ๋จ๊ณ์์ ์์
๊ฐ์ ์ฐ๊ฒฐ ์์
์ ์ํด ์ง์ ํจํค์ง๋ฅผ ๋ถ๋ฌ ํ ๋นํ๋ ์์
์ ๋ถํ๊ฐ ํผ
- ์์ ๋ก๋ฉ ๋์ ํจํค์ง์ ์ค๋ธ์ ํธ๋ฅผ ์ง์ ํ ๋ฌธ์์ด์ ๋์ฒดํด ์ฌ์ฉ. ์ด๋ฅผ ์ค๋ธ์ ํธ ๊ฒฝ๋ก๋ผ ํจ
- ํ๋ก์ ํธ ๋ด์ ์ค๋ธ์ ํธ ๊ฒฝ๋ก ๊ฐ์ ์ ์ผํจ์ ๋ณด์ฅํจ
- ๊ทธ๋ ๊ธฐ์ ์ค๋ธ์ ํธ ๊ฐ์ ์ฐ๊ฒฐ์ ์ค๋ธ์ ํธ ๊ฒฝ๋ก ๊ฐ์ผ๋ก ๊ธฐ๋ก๋ ์ ์์
- ์ค๋ธ์ ํธ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํด ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์์ ์ ๋ก๋ฉํ ์ ์์
- ์์
์ ๋ก๋ฉ ์ ๋ต
- ํ๋ก์ ํธ์์ ์์ ์ด ๋ฐ๋์ ํ์ํ ๊ฒฝ์ฐ : ์์ฑ์ ์ฝ๋์์ ๋ฏธ๋ฆฌ ๋ก๋ฉ
- ๋ฐํ์์์ ํ์ํ ๋ ๋ฐ๋ก ๋ก๋ฉํ๋ ๊ฒฝ์ฐ : ๋ฐํ์ ๋ก์ง์์ ์ ์ ๋ก๋ฉ
- ๋ฐํ์์์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋ฉํ๋ ๊ฒฝ์ฐ : ๋ฐํ์ ๋ก์ง์์ ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ ๋ก๋ฉ
๐ฉ ์ค๋ธ์ ํธ ๊ฒฝ๋ก
- ํจํค์ง ์ด๋ฆ๊ณผ ์์ ์ด๋ฆ์ ํ ๋ฐ ๋ฌถ์ ๋ฌธ์์ด
- ์์ ํด๋์ค ์ ๋ณด๋ ์๋ตํ ์ ์์
- ํจํค์ง ๋ด ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๋ก๋ํ์ง ์๊ณ ์ค๋ธ์ ํธ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํด ํ์ํ ์์ ๋ง ๋ก๋ํ ์ ์์
- {์์ ํด๋์ค ์ ๋ณด}'{ํจํค์ง ์ด๋ฆ}.{์์ ์ด๋ฆ}' or {ํจํค์ง ์ด๋ฆ}.{์์ ์ด๋ฆ}
๐ฉ ์์ ์คํธ๋ฆฌ๋ฐ ๊ด๋ฆฌ์(Steamable Manager)
- ์์ ์ ๋น๋๊ธฐ ๋ก๋ฉ์ ์ง์ํ๋ ๊ด๋ฆฌ์ ๊ฐ์ฒด
- ์ฝํ
์ธ ์ ์๊ณผ ๋ฌด๊ดํ ์ฑ๊ธํด ํด๋์ค์ FStreamableManager๋ฅผ ์ ์ธํด๋๋ฉด ์ข์
- GameInstance๋ ์ข์ ์ ํ์ง
- FStreamableManager๋ฅผ ํ์ฉํด ์์ ์ ๋๊ธฐ/๋น๋๊ธฐ ๋ก๋ฉ์ ๊ด๋ฆฌํ ์ ์์
- ๋ค์์ ์ค๋ธ์ ํธ ๊ฒฝ๋ก๋ฅผ ์ ๋ ฅํด ๋ค์์ ์์ ์ ๋ก๋ฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํจ
๐ MyGameInstance(h, cpp)
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "Engine/StreamableManager.h"
#include "MyGameInstance.generated.h"
struct FStudentData {
FStudentData() {}
FStudentData(int32 InOrder, const FString& InName) : Order(InOrder), Name(InName) {}
friend FArchive& operator<<(FArchive& Ar, FStudentData& InStudentData) {
Ar << InStudentData.Order;
Ar << InStudentData.Name;
return Ar;
}
int32 Order = -1;
FString Name = TEXT("ํ๊ธธ๋");
};
/**
*
*/
UCLASS()
class UNREALSERIALIZATION_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UMyGameInstance();
virtual void Init() override;
void SaveStudentPackage() const;
void LoadStudentPackage() const;
void LoadStudentObject() const;
private:
static const FString PackageName;
static const FString AssetName;
UPROPERTY()
TObjectPtr<class UStudent> StudentSrc;
FStreamableManager StreamableManager;
TSharedPtr<FStreamableHandle> Handle;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
#include "Student.h"
#include "JsonObjectConverter.h"
#include "UObject/SavePackage.h"
const FString UMyGameInstance::PackageName = TEXT("/Game/Student");
const FString UMyGameInstance::AssetName = TEXT("TopStudent");
void PrintStudentInfo(const UStudent* InStudent, const FString& InTag) {
UE_LOG(LogTemp, Log, TEXT("[%s] ์ด๋ฆ %s ์๋ฒ %d"), *InTag, *InStudent->GetName(), InStudent->GetOrder());
}
UMyGameInstance::UMyGameInstance()
{
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
static ConstructorHelpers::FObjectFinder<UStudent> UASSET_TopStudent(*TopSoftObjectPath);
if (UASSET_TopStudent.Succeeded()) {
PrintStudentInfo(UASSET_TopStudent.Object, TEXT("Constructor"));
}
}
void UMyGameInstance::Init()
{
Super::Init();
FStudentData RawDataSrc(16, TEXT("์ด๋์ฐ"));
const FString SavedDir = FPaths::Combine(FPlatformMisc::ProjectDir(), TEXT("Saved"));
UE_LOG(LogTemp, Log, TEXT("์ ์ฅํ ํ์ผ ํด๋ : %s"), *SavedDir);
{
const FString RawDataFileName(TEXT("RawData.bin"));
FString RawDataAbsolutePath = FPaths::Combine(*SavedDir, *RawDataFileName);
UE_LOG(LogTemp, Log, TEXT("์ ์ฅํ ํ์ผ ์ ์ฒด ๊ฒฝ๋ก : %s"), *RawDataAbsolutePath);
FPaths::MakeStandardFilename(RawDataAbsolutePath);
UE_LOG(LogTemp, Log, TEXT("๋ณ๊ฒฝํ ํ์ผ ์ ์ฒด ๊ฒฝ๋ก : %s"), *RawDataAbsolutePath);
FArchive* RawFileWriterAr = IFileManager::Get().CreateFileWriter(*RawDataAbsolutePath);
if (nullptr != RawFileWriterAr) {
*RawFileWriterAr << RawDataSrc;
RawFileWriterAr->Close();
delete RawFileWriterAr;
RawFileWriterAr = nullptr;
}
FStudentData RawDataDest;
FArchive* RawFileReaderAr = IFileManager::Get().CreateFileReader(*RawDataAbsolutePath);
if (nullptr != RawFileReaderAr) {
*RawFileReaderAr << RawDataDest;
RawFileReaderAr->Close();
delete RawFileReaderAr;
RawFileReaderAr = nullptr;
UE_LOG(LogTemp, Log, TEXT("[RawData] ์ด๋ฆ %s, ์๋ฒ %d"), *RawDataDest.Name, RawDataDest.Order);
}
}
StudentSrc = NewObject<UStudent>();
StudentSrc->SetName(TEXT("์ด๋์ฐ"));
StudentSrc->SetOrder(59);
{
const FString ObjectDataFileName(TEXT("ObjectData.bin"));
FString ObjectDataAbsolutePath = FPaths::Combine(*SavedDir, *ObjectDataFileName);
FPaths::MakeStandardFilename(ObjectDataAbsolutePath);
TArray<uint8> BufferArray;
FMemoryWriter MemoryWriterAr(BufferArray);
StudentSrc->Serialize(MemoryWriterAr);
if (TUniquePtr<FArchive> FileWriterAr = TUniquePtr<FArchive>(IFileManager::Get().CreateFileWriter(*ObjectDataAbsolutePath))) {
*FileWriterAr << BufferArray;
FileWriterAr->Close();
}
TArray<uint8> BufferArrayFromFile;
if (TUniquePtr<FArchive> FileReaderAr = TUniquePtr<FArchive>(IFileManager::Get().CreateFileReader(*ObjectDataAbsolutePath))) {
*FileReaderAr << BufferArrayFromFile;
FileReaderAr->Close();
}
FMemoryReader MemoryReaderAr(BufferArrayFromFile);
UStudent* StudentDest = NewObject<UStudent>();
StudentDest->Serialize(MemoryReaderAr);
PrintStudentInfo(StudentDest, TEXT("ObjectData"));
}
// json ์ง๋ ฌํ
{
const FString JsonDataFileName(TEXT("StudentJsonData.txt"));
FString JsonDataAbsolutePath = FPaths::Combine(*SavedDir, *JsonDataFileName);
FPaths::MakeStandardFilename(JsonDataAbsolutePath);
TSharedRef<FJsonObject> JsonObjectSrc = MakeShared<FJsonObject>();
FJsonObjectConverter::UStructToJsonObject(StudentSrc->GetClass(), StudentSrc, JsonObjectSrc);
FString JsonOutString;
TSharedRef<TJsonWriter<TCHAR>> JsonWriterAr = TJsonWriterFactory<TCHAR>::Create(&JsonOutString);
if (FJsonSerializer::Serialize(JsonObjectSrc, JsonWriterAr)) {
FFileHelper::SaveStringToFile(JsonOutString, *JsonDataAbsolutePath);
}
FString JsonInString;
FFileHelper::LoadFileToString(JsonInString, *JsonDataAbsolutePath);
TSharedRef<TJsonReader<TCHAR>> JsonReaderAr = TJsonReaderFactory<TCHAR>::Create(JsonInString);\
TSharedPtr<FJsonObject> JsonObjectDest;
if (FJsonSerializer::Deserialize(JsonReaderAr, JsonObjectDest)) {
UStudent* JsonStudentDest = NewObject<UStudent>();
if(FJsonObjectConverter::JsonObjectToUStruct(JsonObjectDest.ToSharedRef(), JsonStudentDest->GetClass(), JsonStudentDest)) {
PrintStudentInfo(JsonStudentDest, TEXT("JsonData"));
}
}
}
// ํจํค์ง๋ฅผ ์ฌ์ฉํ ์์
์ ์ฅ
SaveStudentPackage();
//LoadStudentPackage();
//LoadStudentObject();
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
Handle = StreamableManager.RequestAsyncLoad(TopSoftObjectPath,
[&]() {
if (Handle.IsValid() && Handle->HasLoadCompleted()) {
UStudent* TopStudent = Cast<UStudent>(Handle->GetLoadedAsset());
if (TopStudent) {
PrintStudentInfo(TopStudent, TEXT("AsyncLoad"));
Handle->ReleaseHandle();
Handle.Reset();
}
}
}
);
}
void UMyGameInstance::SaveStudentPackage() const
{
UPackage* StudentPackage = ::LoadPackage(nullptr, *PackageName, LOAD_None);
if (StudentPackage) {
StudentPackage->FullyLoad();
}
StudentPackage = CreatePackage(*PackageName);
EObjectFlags ObjectFlag = RF_Public | RF_Standalone;
UStudent* TopStudent = NewObject<UStudent>(StudentPackage, UStudent::StaticClass(), *AssetName, ObjectFlag);
TopStudent->SetName(TEXT("์ด๋์ฐ"));
TopStudent->SetOrder(36);
const int32 NumOfSubs = 10;
for (int32 ix = 1; ix <= NumOfSubs; ++ix) {
FString SubObjectName = FString::Printf(TEXT("Student%d"), ix);
UStudent* SubStudent = NewObject<UStudent>(TopStudent, UStudent::StaticClass(), *SubObjectName, ObjectFlag);
SubStudent->SetOrder(ix);
}
const FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
FSavePackageArgs SaveArgs;
SaveArgs.TopLevelFlags = ObjectFlag;
if (UPackage::SavePackage(StudentPackage, nullptr, *PackageFileName, SaveArgs)) {
UE_LOG(LogTemp, Log, TEXT("ํจํค์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ ์ฅ๋์์ต๋๋ค."));
}
}
void UMyGameInstance::LoadStudentPackage() const
{
UPackage* StudentPackage = ::LoadPackage(nullptr, *PackageName, LOAD_None);
if (nullptr == StudentPackage) {
UE_LOG(LogTemp, Warning, TEXT("ํจํค์ง๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค."));;
return;
}
StudentPackage->FullyLoad();
UStudent* TopStudent = FindObject<UStudent>(StudentPackage, *AssetName);
PrintStudentInfo(TopStudent, TEXT("FindObject Asset"));
}
void UMyGameInstance::LoadStudentObject() const
{
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
UStudent* TopStudent = LoadObject<UStudent>(nullptr, *TopSoftObjectPath);
PrintStudentInfo(TopStudent, TEXT("LoadObject Asset"));
}
'โ๏ธ ์์ง > ๐ซ ์ธ๋ฆฌ์ผ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Unreal] ์ธ๋ฆฌ์ผ C++ ํ์ต๋ฐฉ๋ฒ (0) | 2024.05.14 |
---|---|
[Unreal] ์ธ๋ฆฌ์ผ ๋น๋ ์์คํ (0) | 2024.05.08 |
[Unreal] ์ธ๋ฆฌ์ผ ์ค๋ธ์ ํธ ๊ด๋ฆฌ1 - ์ง๋ ฌํ (0) | 2024.05.08 |
[Unreal] ์์ํด์ ์ธ๋ฆฌ์ผ 2024 - 1. ๋ ๋ฒจ ์ ์ํ๊ธฐ (0) | 2024.05.05 |
[Unreal] ์ธ๋ฆฌ์ผ ์์ง์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ (0) | 2024.05.05 |