728x90
반응형
- 정리
- 언리얼 오브젝트 직렬화
- 언리얼 엔진이 제공하는 직렬화 시스템에 대한 이해
- FArchive클래스를 활용한 메모리 아카이브와 파일 아카이브의 활용
- JSonSerializer를 사용한 JSON 형식의 직렬화 기능의 활용
- 일반 C++ 객체 관리를 위한 언리얼 스마트 포인터 라이브러리의 활용
- 언리얼 오브젝트 직렬화
- 직렬화(Serialization)란?
- 오브젝트나 연결된 오브젝트의 묶음(오브젝트 그래프)을 바이트 스트림으로 변환하는 과정
- 복잡한 데이터를 일렬로 세우기 때문에 직렬화
- 거꾸로 복구시키는 과정도 포함해서 의미
- 시리얼라이제이션(Serialization)
- 오브젝트 그래프에서 바이트 스트림으로
- 디시리얼라이제이션(Deserialization)
- 바이트 스트림에서 오브젝트 그래프로
- 시리얼라이제이션(Serialization)
- 직렬화가 가지는 장점
- 현재 프로그램의 상태를 저장하고 필요한 때 복원할 수 있음 (게임의 저장…)
- 현재 객체의 정보를 클립보드에 복사해서 다른 프로그램에 전송할 수 있다.
- 네트워크를 통해 현재 프로그램의 상태를 다른 컴퓨터에 복원할 수 있다. (멀티플레이어 게임)
- 데이터 압축, 암호화를 통해 데이터를 효율적이고 안전하게 보관할 수도 있음
- 오브젝트나 연결된 오브젝트의 묶음(오브젝트 그래프)을 바이트 스트림으로 변환하는 과정
- 직렬화 구현시 고려할 점
- 데이터 레이아웃
- 오브젝트가 소유한 다양한 데이터를 변환할 것인가?
- 이식성
- 서로 다른 시스템에 전송해도 이식될 수 있는가?
- 버전 관리
- 새로운 기능이 추가될 때 이를 어떻게 확장하고 처리할 것인가?
- 성능
- 네트웍 비용을 줄이기 위해 어떤 데이터 형식을 사용할 것인가?
- 보안
- 데이터를 어떻게 안전하게 보호할 것인가?
- 에러 처리
- 전송 과정에서 문제가 발생할 경우 이를 어떻게 인식하고 처리할 것인가?
- 데이터 레이아웃
- 언리얼 엔진의 직렬화 시스템
- 언리얼 엔진은 직렬화 시스템을 자체적으로 제공하고 있음
- 직렬화 시스템을 위해 제공하는 클래스 FArchive와 연산자
- 아카이브 클래스 (FArchive)
- Shift (<<) operator
- 다양한 아카이브 클래스의 제공
- 메모리 아카이브 (FMemoryReader, FMemoryWriter)
- 파일 아카이브 (FArchiveFileReaderGeneric, FArchiveFileWriterGeneric)
- 기타 언리얼 오브젝트와 관련된 아카이브 클래스 (FArchiveUObject)
- Json 직렬화 기능
- 별도의 라이브러리를 통해 제공하고 있음
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("홍길동");
};
- MyGameInstance.h
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 RawDataAbosolutePath = FPaths::Combine(*SavedDir, *RawDataFileName);
UE_LOG(LogTemp, Log, TEXT("저장할 파일 전체 경로 : %s"), *RawDataAbosolutePath);
FPaths::MakeStandardFilename(RawDataAbosolutePath); // 숨겨진 파일 전체 경로를 볼 수 있도록 변경해줌
UE_LOG(LogTemp, Log, TEXT("변경할 파일 전체 경로 : %s"), *RawDataAbosolutePath);
FArchive* RawFileWriterAr = IFileManager::Get().CreateFileWriter(*RawDataAbosolutePath); // Writer
if (nullptr != RawFileWriterAr)
{
*RawFileWriterAr << RawDataSrc; // 헤더파일에서 << 오퍼레이션을 통해 손쉽게 데이터를 가져오기 가능
RawFileWriterAr->Close(); // 파일을 열었으면 닫아주고
delete RawFileWriterAr; // 해제해주고
RawFileWriterAr = nullptr; // 삭제까지 해준다.
}
FStudentData RawDataDest;
FArchive* RawFileReaderAr = IFileManager::Get().CreateFileReader(*RawDataAbosolutePath); // Reader
if (nullptr != RawFileReaderAr)
{
*RawFileReaderAr << RawDataDest;
RawFileReaderAr->Close();
delete RawFileReaderAr;
RawFileReaderAr = nullptr;
UE_LOG(LogTemp, Log, TEXT("[RawData] 이름 %s 순번 %d"), *RawDataDest.Name, RawDataDest.Order); // 정상적으로 읽고, 써졌는지 확인하기
}
}
}
- MyGameInstance.cpp
- 언제나 파일의 내용을 읽어올때, 멤버 변수를 지정해줄 수 없으니 Shift (<<) operator를 통해 사용하면 된다.
- Json 직렬화
- Json(JavaScript Object Notation)의 약자
- 엡 환경에서 서버와 클라이언트 사이에 데이터를 주고받을 때 사용하는 텍스트 기반 데이터 포맷
- Json 장점
- 텍스트임에도 데이터 크기가 가벼움
- 읽기 편해서 데이터를 보고 이해할 수 있음
- 사실 상 웹 통신의 표준으로 널리 사용됨
- Json의 단점
- 지원하는 타입이 몇 가지 안됨 (문자, 숫자, 불리언, 널, 배열, 오브젝트만 사용 가능)
- 텍스트 형식으로만 사용할 수 있음
- 언리얼 엔진의 Json, JsonUtilities 라이브러리 활용
- Json 데이터 예시
- Json 데이터 유형
- 오브젝트 : {}
- 오브젝트 내 데이터는 키, 밸류 조합으로 구성됨. 예) {”key” : 10}
- 배열 : []
- 배열 내 데이터는 밸류로만 구성됨
- 이외 데이터
- 문자열 (”string”), 숫자 (10 또는 3.14 …), 불리언 (true 또는 false), 널 (null)로 구성
- 오브젝트 : {}
- Json 데이터 유형
- 언리얼이 제공하는 Json 라이브러리를 사용하려면 언리얼 엔진이 제공하는 스마트 포인터 라이브러리를 알아두면 좋다.
- 언리얼 스마트 포인터 라이브러리 개요
- 일반 C++ 오브젝트의 포인터 문제를 해결해주는 언리얼 엔진의 라이브러리
- TUniquePtr(유니크포인터) : 지정한 곳에서만 메모리를 관리하는 포인터
- 특정 오브젝트에게 명확하게 포인터 해지 권한을 주고 싶은 경우
- delete 구문 없이 함수 실행 후 자동으로 소멸시키고 싶을 때
- TSharedPtr(공유포인터) : 더 이상 사용되지 않으면 자동으로 메모리를 해지하는 포인터
- 여러 로직에서 할당된 오브젝트가 공유해서 사용되는 경우
- 다른 함수로부터 할당된 오브젝트를 Out으로 받는 경우
- Null 일 수 있음
- TSharedRef(공유레퍼런스) : 공유포인터와 동일하지만, 유효한 객체를 항상 보장받는 레퍼런스
- 여러 로직에서 할당된 오브젝트가 공유해서 사용되는 경우
- Not Null을 보장받으며 오브젝트를 편리하게 사용하고 싶은 경우
using UnrealBuildTool;
public class UnrealSerialization : ModuleRules
{
public UnrealSerialization(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Json", "JsonUtilities" }); // Json과 관련된 모듈 선언 및 추가
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
- UnrealSerialization.Bulid.cs 에 Json에 관련된 모듈 추가하기
{
const FString JsonDataFileName(TEXT("StudentJsonData.txt"));
FString JsonDataAbsolutePath = FPaths::Combine(*SavedDir, *JsonDataFileName);
FPaths::MakeStandardFilename(JsonDataAbsolutePath);
TSharedRef<FJsonObject> JsonObjectSrc = MakeShared<FJsonObject>(); // TSharedRef를 통해 Not Null을 보장받음
FJsonObjectConverter::UStructToJsonObject(StudentSrc->GetClass(), StudentSrc, JsonObjectSrc);
FString JsonOutString; // Json으로 내보낼
TSharedRef<TJsonWriter<TCHAR>> JsonWriterAr = TJsonWriterFactory<TCHAR>::Create(&JsonOutString); // Json으로 써주는
if (FJsonSerializer::Serialize(JsonObjectSrc, JsonWriterAr)) // 직렬화 진행이 성공했다면
{
FFileHelper::SaveStringToFile(JsonOutString, *JsonDataAbsolutePath); // 파일에 Json을 쓰기
}
FString JsonInString; // Json으로 불러드릴
FFileHelper::LoadFileToString(JsonInString, *JsonDataAbsolutePath);
TSharedRef<TJsonReader<TCHAR>> JsonReaderAr = TJsonReaderFactory<TCHAR>::Create(JsonInString);
TSharedPtr<FJsonObject> JsonObjectDest; // Null이 들어갈 수도 있으니 Ptr로 선언
if (FJsonSerializer::Deserialize(JsonReaderAr, JsonObjectDest))
{
UStudent* JsonStudentDest = NewObject<UStudent>();
if (FJsonObjectConverter::JsonObjectToUStruct(JsonObjectDest.ToSharedRef(), JsonStudentDest->GetClass(), JsonStudentDest)) // Json 오브젝트를 언리얼 오브젝트로 변환
{
PrintStudentInfo(JsonStudentDest, TEXT("JsonData"));
}
}
}
- MyGameInstance.cpp / Json 오브젝트를 내보내거나, 가져와 사용하는 방법
해당 포스트는 인프런의 <이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해>
강의를 수강하고 정리한 내용입니다.
이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해 | 이득우 - 인프런
이득우 | 대기업 현업자들이 수강하는 언리얼 C++ 프로그래밍 전문 과정입니다. 언리얼 엔진 프로그래머라면 게임 개발전에 반드시 알아야 하는 언리얼 C++ 기초에 대해 알려드립니다., [사진] 언.................................
www.inflearn.com
728x90
'공부 > 이득우의 언리얼 프로그래밍' 카테고리의 다른 글
[Study] Part 1 - 언리얼 빌드 시스템 (15/15) (0) | 2024.05.12 |
---|---|
[Study] Part 1 - 언리얼 오브젝트 관리 II - 패키지 (14/15) (0) | 2024.05.09 |
[Study] Part1 - 언리얼 엔진의 메모리 관리 (12/15) (0) | 2024.05.07 |
[Study] Part 1 - 언리얼 컨테이너 라이브러리 II - 구조체와 Map (11/15) (0) | 2024.05.03 |
[Study] Part 1 - 언리얼 컨테이너 라이브러리 I - Array와 Set (10/15) (0) | 2024.05.02 |