저장 게임
저장 게임은 게임 세션 간 기계 및 상태 정보를 유지하는 데 필수적입니다. 저장 게임은 인벤토리에 있는 아이템과 같은 정보도 포함합니다. 일반적으로 새티스팩토리는 현재 게임 상태를 5분마다 자동으로 저장합니다. 물론, 게임 내에서 저장 버튼을 눌러 직접 게임 상태를 저장할 수도 있습니다.
저장 파일은 %localappdata%/FactoryGame/Saved/SaveGames/
에서 찾을 수 있습니다.
하지만 "저장" 버튼을 누르면 실제로 어떤 일이 발생할까요?
게임 상태가 어떻게 저장됩니까?
저장 또는 로드가 발생할 때, 언리얼은 현재 로드된 세계를 직렬화합니다. 이 과정은 기본적으로 런타임의 모든 액터와 객체를 이진 데이터로 변환하여 나중에 다시 읽어 현재 런타임을 재구성할 수 있도록 합니다.
하지만 전체 런타임을 저장하지는 않습니다. 그렇게 되면 저장 파일이 너무 커지기 때문입니다. 따라서 직렬화에서는 여러 가지 방법으로 많은 것들이 제외됩니다. 기본적으로, 여러분의 객체는 직렬화되지 않으며, 언리얼에게 직렬화하고 싶다고 알려야 합니다.
세계의 모든 AActor
또는 UActorComponent
는 직렬화될 것으로 간주되지만, 여전히 너무 많기 때문에,
CSS는 IFGSaveInterface를 추가하여 추가 필터링을 가능하게 합니다.
직렬화하고 싶은 어떤 AActor
가 있는 경우, ShouldSave
함수를 오버라이드하고 true를 반환해야 합니다.
액터가 직렬화될 때, 이는 두 단계로 진행됩니다.
첫 번째 단계에서는 언리얼 직렬화 과정이 실행되지만, 직렬화 가능한 UObject
만 처리합니다.
따라서 이 단계에서는 직렬화해야 할 모든 UObject
의 목록을 수집합니다.
그 후 CSS는 IFGSaveInterface::GatherDependencies
의 결과를 고려하여 이 목록을 정렬합니다.
이것은 UObject
가 의존하는 다른 UObject
를 정의할 수 있도록 합니다.
이것은 저장 로드 시 역직렬화 단계에서 중요할 수 있습니다.
왜냐하면 의존하는 UObject
가 먼저 완전히 역직렬화되기를 여러분이 원할 수 있기 때문입니다.
|
두 번째 단계에서는 이전에 결정된 UObject
순서를 고려하여
실제 언리얼 직렬화 과정이 실행됩니다.
"언리얼 직렬화"는 두 가지 방법으로 발생할 수 있으며,
자신의 직렬화 과정을 구현하거나 UProperties
를 통해
언리얼의 기본 방식을 사용할 수 있습니다(권장).
필요한 경우, UObject
또는 구조체에 맞춤 직렬화를 추가하는 방법에 대한
자세한 내용은 언리얼 문서를 참고하십시오.
언리얼의 기본 직렬화 방식은 SkipSerialization
속성 플래그가 없고 SaveGame
속성 플래그가 있는 UProperties
를 검색합니다.
UProperty
가 UObject
참조인 경우, 해당 UObject
도 직렬화됩니다.
이러한 직렬화가 진행되는 동안, 새티스팩토리 저장 시스템은 직렬화되는 모든 AActor
에 대해 PreSaveGame
, PostSaveGame
, PreLoadGame
, PostLoadGame
함수를 호출합니다.
SaveGame UProperty 플래그
모든 속성이 직렬화되는 것은 아닙니다.
오직 SaveGame
플래그가 있는 UProperties
만 실제로 직렬화됩니다.
블루프린트 작업 시, 고급 속성 설정을 열고 SaveGame
박스를 체크하여 이 플래그를 추가할 수 있습니다.
C++ 작업 시, IFGSaveInterface
를 사용하는 방법에 대한 지침을 따라야 합니다.
속성이나 객체에 어쨌든, 기본적으로 설정되어 있지 않아야 합니다. |
모든 유형이 직접 저장될 수 있는 것은 아닙니다.
이의 예로는 소프트 클래스 참조와 소프트 객체 참조 유형이 있습니다.
이 경우, 위에서 설명한 대로 해당 유형을 직접 직렬화하는 코드를 작성해야 합니다.
소프트 클래스 참조의 예를 들자면, 소프트 클래스 참조 속성을 저장하는 대신,
저장된 문자열 속성을 사용하여 PreSaveGame
에서 복사하고 PostLoadGame
에서 "실제" 필드를 채워야 합니다.
IFGSaveInterface
새티스팩토리의 저장 시스템은 IFGSaveInterface를 사용하여 저장해야 할 객체와 그렇지 않은 객체를 필터링합니다.
가장 중요한 함수 중 하나는 bool ShouldSave() const
함수로,
객체가 저장되어야 할 때 true를 반환합니다.
이는 객체의 상태에 따라 달라질 수 있습니다.
예를 들어, 나무는 실제로 게임에서 베어졌을 때만 true를 반환합니다.
즉,
게임 세션 간에 유지하고 싶은 정보가 있다면, IFGSaveInterface
를 구현하고
ShouldSave
에서 true를 반환해야 합니다.
|
다른 모든 함수는 저장 상태가 저장되거나 로드될 때 직렬화 및 필터링 과정을 추가로 맞춤 설정할 수 있게 합니다.
플레이어별 데이터 저장
멀티플레이 게임에서 건물이나 장비와 같은 구체적인 게임 객체에 묶이지 않고 플레이어별로 데이터를 저장해야 하는 상황이 발생할 수 있습니다. 이를 구현하는 가장 좋은 방법은 간단 구축 스크립트(SCS) 훅을 사용하는 것입니다.
모드 저장 콘텐츠가 위치하는 곳
원하는 경우, 모드 저장을 에디터에서 확인하여 데이터가 어떻게 저장되는지 살펴볼 수 있습니다.
일반적으로 모드에서 생성된 콘텐츠는 Game/<모드_참조>/
태그 아래에 나타납니다.
아래는 NogsOres라는 참조가 있는 모드의 데이터를 표시하는 SatisfactorySaveEditor의 스크린샷입니다.
저장 파일 구조
저장 파일 형식에 대한 자세한 내용은 다음 자원을 통해 확인할 수 있습니다:
-
오픈 소스 도구를 살펴보며 그들이 기능을 어떻게 구현했는지 확인하십시오.