// 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("Student");
// 5.3버전에서는 PackageName과 AssetName을 동일하게 사용해야 콘텐츠 브라우져에서 보임.
void PrintStudentInfo(const UStudent* InStudent, const FString& InTag)
{
UE_LOG(LogTemp, Log, TEXT("[%s] 이름 %s 순번 %d"), *InTag, *InStudent->GetName(), InStudent->GetOrder());
}
UMyGameInstance::UMyGameInstance()
{
}
void UMyGameInstance::Init()
{
Super::Init();
SaveStudentPackage();
LoadStudentPackage();
}
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->SetName(FString::Printf(TEXT("학생%d"), ix));
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, Log, TEXT("패키지를 찾을 수 없습니다."));
return;
}
StudentPackage->FullyLoad();
// 패키지 안에서 UStudent 타입의 언리얼 오브젝트를 찾아서 반환을 시켜준다.
UStudent* TopStudent = FindObject<UStudent>(StudentPackage, *AssetName);
PrintStudentInfo(TopStudent, TEXT("FindObject Asset"));
}
{애셋클래스정보}'{패키지이름}.{애셋이름}' 또는 {패키지이름}.{애셋이름}
UMyGameInstance::UMyGameInstance()
{
// 생성자에서 애셋을 로딩하는 경우는 게임이 시작하기 전에 미리 다 메모리에 올라와 있어야 된다는 것을 의미.
// 생성자에서 애셋을 로드할 때는 LoadObject를 쓰는 것이 아니고 언리얼에서 제공하는 컨스트럭터 핼퍼스 사용을 해줘야 한다.
const FString TopSoftObjectPath = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
static ConstructorHelpers::FObjectFinder<UStudent> UASSET_TopStudent(*TopSoftObjectPath);
// Succeeded(): 로딩이 제대로 됐는지를 확인할 수 있는 함수.
if (UASSET_TopStudent.Succeeded())
{
PrintStudentInfo(UASSET_TopStudent.Object, TEXT("Constructor"));
}
/*
LogTemp: [Constructor] 이름 명랑코딩 순번 36
LogTemp: [Constructor] 이름 명랑코딩 순번 36
로그가 두 번 찍힌 것을 볼 수가 있다.
첫 번째는 에디터가 로딩될 때 찍혔다.
두 번째는 에디터 내 게임이 실행할 때 컨스트럭터에 관련된 함수들이 자동으로 호출되기 때문에 두 번 찍히게 된다.
생성자 코드에서 지정한 애셋이 존재하지 않는 경우에는 시작할 때 경고와 에러 메시지가 뜬다.
*/
}
void UMyGameInstance::Init()
{
Super::Init();
SaveStudentPackage();
//LoadStudentPackage();
LoadStudentObject();
}
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"));
}
// 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:
// 패키지를 사용하기 위해서는 패키지와 패키지가 담고 있는 대표 asset을 설정해줘야 된다.
// 이것들의 이름을 지정.
static const FString PackageName;
static const FString AssetName;
UPROPERTY()
TObjectPtr<class UStudent> StudentSrc;
// 비동기 로딩.
FStreamableManager StreamableManager;
// 스트리밍된 asset을 관리할 수 있는 핸들 지정.
TSharedPtr<FStreamableHandle> Handle;
};
void UMyGameInstance::Init()
{
Super::Init();
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();
}
}
}
);
}