작성
·
34
·
수정됨
0
22:43 부분에서, 제가 실수로
void UStudent::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
Ar << Name;
}
처럼 Ar<<Order; 를 적지 않은 상태에서 31:19 부분까지 진행을 하였고, 출력 결과가 놀랍게도 "[ObjectData] 이름 이득우 순번 59" 가 출력이 되었습니다.
분명 StudentSrc->Serialize(MemoryWriterAr); 에서 Ar << Order; 가 누락되어서 직렬화를 진행하지 못했고, BufferArray 에는 59 라는 Order가 저장되지 않았을 것일텐데, 따라서 결과적으로 print함수를 통해 순번이 59가 아닌 생성자에서 설정한 -1로 떠야 한다고 생각하지만 이상하게도 59라는 숫자가 출력됩니다.
이 말은 Ar<<Order; 를 누락했더라도 내부적으로 알아서 직렬화를 진행했다고 볼수밖에 없는 것일까요...?
만약 그렇다면 어떤 코드부분에서 StudentSrc의 Order를 MemoryWriterAr가 소유한 BufferArray 에 저장하게 되는 것인지 궁금합니다.
다음은 저의 코드입니다.
(제가 실수하지 않았다면, 사실상 Student.cpp ->void UStudent::Serialize(FArchive& Ar) 함수에서 Ar << Order; 가 누락된 것을 제외하고 전부 동일합니다.)
//MyGameInstance.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.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;
private:
UPROPERTY()
TObjectPtr<class UStudent> StudentSrc;
};
//MyGameInstance.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameInstance.h"
#include "Student.h"
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();
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;
/*RawDataSrc << RawFileWriterAr;/
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"));
}
}
//Student.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Student.generated.h"
/**
*
*/
UCLASS()
class UNREALSERIALIZATION_API UStudent : public UObject
{
GENERATED_BODY()
public:
UStudent();
int32 GetOrder() const { return Order; }
void SetOrder(int32 InOrder) { Order = InOrder; }
const FString& GetName() const { return Name; }
void SetName(const FString& InName) { Name = InName; }
virtual void Serialize(FArchive& Ar) override;
private:
UPROPERTY()
int32 Order;
UPROPERTY()
FString Name;
};
//Student.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Student.h"
UStudent::UStudent()
{
Order = -1;
Name = TEXT("홍길동");
}
void UStudent::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
Ar << Name;
}
답변 2
1
좋은 질문입니다.
FArchive 클래스가 보관하는 데이터는 변수 이름과 값의 쌍으로 구성되어 있습니다. 그리고 순서는 기본적으로 UPROPERTY의 배치 순서를 따릅니다. 이것이 상위클래스 함수인 Super::Serialize(Ar) 가 진행하는 내용으로 간략하게 이해해주시면 될 것 같습니다.
그렇기에 현재 예제에서 Super::Serialize(Ar) 아래의 코드는 사실 큰 의미는 없지요.
( 보통은 로컬 변수를 선언해서 기본 UPROPERTY가 아닌 부가 데이터를 심거나 불러오는데 사용합니다. )
만일 질문 주신대로 특정 필드 값만 넣고 싶다면 Super::Serialize(Ar) 라인을 삭제한 후에 원하는 UPROPERTY에 대해서만 << 연산자를 사용해주면 됩니다.
조금 더 고급적인 내용은 네트워크 Part3에서 다루고 있습니다.
질문을 듣고보니 예제 구성에서 Super::Serialize(Ar) 라인을 삭제하거나 관련 설명을 추가하는 것이 보다 좋겠네요.
감사합니다!
0
안녕하세요, 인프런 AI 인턴입니다.
이번 질문에서는 직렬화에 관한 부분을 살펴보고 싶으신 것 같습니다. 언급하신 문제에서 가장 중요한 부분은 Ar << Order;
가 누락되었음에도 정상적인 값이 출력되는 이유에 대한 의문입니다.
직렬화와 기본 생성자: UStudent
클래스에서는 Order
가 기본적으로 -1로 설정되어 있지만, StudentSrc->SetOrder(59);
로 명시적으로 값을 설정하셨습니다. 여기서 핵심은 StudentDest
객체가 초기화될 때, Serialize
함수 내에서 Order
값을 제대로 저장하거나 읽어오지 않더라도, 이전에 설정한 값이 계속 유지된다는 점입니다.
직렬화의 동작 방식: 기본적으로, 언리얼 엔진에서 Serialize
함수는 부모 클래스의 Serialize
도 호출하지만 이때는 해당 클래스에서 명시한 멤버 데이터들만 직렬화합니다. Ar << Name;
만 호출하면 Order
값은 변경되거나 저장되지 않으므로, 원래 저장된 값을 유지하게 됩니다.
메모리 상태 유지: StudentSrc
가 Order
에 59를 설정한 상태고, Serialize
에서 Order
가 변경되지 않았습니다. 따라서 이 설정이 직렬화 이전과 이후에도 지속되어 출력값이 영향을 받은 것으로 보입니다.
문제를 해결하기 위해서는 UStudent::Serialize
함수 내에서 Ar << Order;
부분도 반드시 포함되어야 함을 기억하세요. 이는 직렬화를 통해 객체의 상태를 온전히 저장하고 불러오는 데 필수적입니다.
아래는 질문의 이해를 돕기 위한 관련된 질문 URL입니다:
- 13강 언리얼 오브젝트 직렬화와 관련된 질문
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.