퍼시스턴스 데이터를 사용하면 플레이 세션 간에 플레이어별 데이터를 추적하고 저장할 수 있습니다. 이를 통해 플레이어가 떠났다가 다시 돌아와서 목표를 재개하거나, 떠났을 때와 동일한 게임 스테이트를 볼 수 있는 다양한 진행형 게임 모드를 만들 수 있습니다.
퍼시스턴스 데이터는 Verse에서 개별 플레이어마다 프로필이나 통계 등의 데이터를 저장하는 방식으로 작동합니다. 그런 다음 이 데이터를 데이터 값이 변경되는 횟수만큼 업데이트할 수 있습니다. 퍼시스턴스 데이터이므로 여러 게임 세션에 걸쳐 유지되며, 플레이어가 게임에서 온라인 상태인 경우라면 언제든지 사용할 수 있습니다.
퍼시스턴스 데이터를 활용하는 게임 모드의 예시로 서바이벌, 타이쿤, RPG, 로그라이트가 있습니다. 이러한 타입의 게임 모드에서 플레이어는 게임플레이의 원동력이 되는 장기적 목표를 달성하기 위해 아이템을 모아야 합니다.
Verse 스크립트에서 퍼시스턴스 데이터를 사용하여 플레이어별, 모듈별로 정보를 저장합니다. 계속 진행할 동기를 부여하여 플레이어를 남아 있게 만들고자 하는 게임 모드에 퍼시스턴스 데이터를 구현하세요.
퍼시스턴스 구현을 직접 연습해 보려면 퍼시스턴스 플레이어 통계 튜토리얼을 확인하세요.
퍼시스턴스 데이터는 Verse에서 생성하고 사용할 수 있지만, 퍼시스턴스 데이터를 지원하는 기본 기능을 지닌 포크리 장치도 있습니다. 자세한 내용은 퍼시스턴스 장치를 참고하세요.
Verse에서 퍼시스턴스의 의미
Verse에서 모듈에 정의된 변수는 해당 변수가 스코프 안에 있으면 실행 중인 모든 게임 인스턴스에서 전역적으로 적용됩니다. session과 연관된 모듈 스코프 변수를 제외하면, 모듈 스코프 변수는 현재 게임 외의 데이터를 저장하는 퍼시스턴스를 필요로 합니다. 이로 인해 모듈 스코프에서 사용 가능한 타입에는 제한이 있습니다.
현재 다음과 같은 타입을 모듈 스코프에서 사용할 수 있습니다.
| 허용된 모듈 스코프 타입 | 정의 | 제한 |
|---|---|---|
|
| 데이터는 현재 세션 중에만 저장되며, 다음 라운드에서 유지되지 않습니다. |
|
| 플레이어의 퍼시스턴스 데이터에 대한 액세스는 플레이어가 현재 게임에 있을 때만 허용됩니다. |
플레이어가 게임을 떠나거나 현재 세션에 있지 않은 경우, 해당 게임 세션에서 더 이상 데이터를 저장하거나 액세스할 수 없습니다. 플레이어가 돌아오거나 같은 게임을 다시 플레이하는 경우에는 데이터 액세스 및 업데이트가 가능합니다.
Verse에서 퍼시스턴스 데이터 생성하기
플레이어가 게임에 다시 합류할 때마다 지속적으로 업데이트되고, 저장되고, 다시 호출되는 플레이어별 퍼시스턴스 데이터를 직접 생성할 수 있습니다. 매치메이킹 중에 게임은 신규 플레이어의 퍼시스턴스 데이터를 확인합니다. 플레이어가 사용 가능한 퍼시스턴스 데이터를 보유한 경우, 데이터가 로드되어 Verse 스크립트에서 사용할 수 있게 됩니다.
플레이어가 섬의 퍼시스턴스 데이터를 보유했는데 데이터 로드에 실패하는 경우, 플레이어는 섬에 합류할 수 없습니다. 이는 데이터 로드에 실패하는 경우 퍼시스턴스 데이터를 덮어쓰지 않도록 방지하는 보호 조치입니다.
Verse 코드에서 퍼시스턴스 데이터를 생성하려면, player 타입을 키로 사용하고 퍼시스턴스 타입을 값으로 사용하는 글로벌 weak_map 변수를 정의합니다. 퍼시스턴스가 될 수 있는 타입의 전체 목록은 퍼시스턴스 타입을 참고하세요.
다음 예시에서 글로벌 'weak_map' 변수 MySavedPlayerData는 플레이어 타입을 키로, 인티저를 값으로 사용합니다. 이 변수에서 플레이어의 인티저 값을 저장하면 데이터가 여러 게임 세션에 걸쳐 유지되며, 플레이어가 게임에 있을 때 언제든지 데이터에 액세스하고 업데이트할 수 있습니다.
var MySavedPlayerData:weak_map(player, int) = map{}
퍼시스턴스 데이터를 정의한 후에는 각 플레이어의 데이터를 초기화해야 합니다. 해당 플레이어에 대해 이미 저장된 데이터가 없는지 확인한 다음, 플레이어 및 초기 값을 weak_map에 추가하는 방식으로 데이터를 초기화할 수 있습니다.
# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void =
InitialSavedPlayerData:int = 0
Players := GetPlayspace().GetPlayers()
for (Player : Players):
if:
not MySavedPlayerData[Player]
set MySavedPlayerData[Player] = InitialSavedPlayerData이전 예시에서는 하나의 인티저 값만 저장했지만, weak_map에 각 플레이어의 데이터를 더 많이 저장하기 위해 클래스, 배열 등의 다른 타입을 사용할 수 있습니다. 사용 가능한 타입의 전체 목록은 퍼시스턴스 타입을 참고하세요.
다음 Verse 예시는 플레이어에 대해 저장하고, 업데이트하고, 나중에 액세스할 수 있는 클래스에서 커스텀 플레이어 프로필을 정의하는 방법을 보여줍니다. player_profile_data 클래스는 플레이어가 획득한 XP, 순위, 완료한 퀘스트 등 플레이어의 정보를 저장합니다.
player_profile_data := class<final><persistable>:
Version:int = 0
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0
CompletedQuestCount:int = 0
QuestHistory:[]string = array{}
var PlayerProfileDataMap:weak_map(player, player_profile_data) = map{}플레이어별, 섬별로 저장할 수 있는 데이터의 양에는 한도가 존재합니다. 데이터를 저장할 때마다 'FitsInPlayerMap' 함수를 사용하여 업데이트가 총 크기에 어떤 영향을 미치는지 확인하는 것이 좋습니다. 자세한 내용은 퍼시스턴스 데이터가 한도 내인지 테스트하기를 확인하세요.
자신만의 퍼시스턴스 데이터를 생성하고 플레이어별로 초기화하는 방법을 알았으니, 이제 모범 사례에서 Verse에서 퍼시스턴스 데이터 작업 시 권장되는 방법을 확인하세요!
섬의 퍼블리싱 버전 간에 데이터 수정하기
섬의 현재 버전을 퍼블리싱한 후 퍼시스턴스 데이터를 업데이트하는 경우, 이전 버전 섬에서 저장한 모든 데이터가 이후 버전 섬에서 지원되어야 합니다.
이를 보장하기 위해 UEFN에서 이전 버전과의 호환성 확인이 실행되며, Verse 코드가 현재 퍼블리싱 버전과 더 이상 호환되지 않는 경우 컴파일에 실패하게 됩니다. 이러한 이전 버전과의 호환성 확인은 다음과 같은 경우에 실행됩니다.
UEFN 툴바에서 세션 시작(Launch Session)을 클릭합니다.
UEFN 툴바에서 변경사항 푸시(Push Changes) 또는 Verse 변경사항 푸시(Push Verse Changes)를 클릭합니다.
처음으로 섬 퍼블리싱하기
섬의 새 퍼블릭 버전 활성화하기
이전 버전과의 호환성 확인은 기본적으로 모듈 스코프 weak_map 변수의 값 타입에 대한 타입 확인입니다. 인티저와 같은 단순 타입의 경우, 섬 퍼블리싱 후 타입이 변경되지 않을 수도 있습니다. 여기에는 섬 퍼블리싱 후 구조체 정의를 변경할 수 없는 structs가 포함됩니다.
현재, 섬 퍼블리싱 후 더 많은 데이터를 추가할 수 있는 유일한 퍼시스턴스 타입은 새 필드가 기본값을 갖는 한 class 타입입니다. 이는 이전 버전에서 저장된 데이터를 로드하면 새 필드 및 새 필드의 기본값이 포함된다는 뜻입니다. 클래스를 퍼시스턴스 데이터로 사용하는 것에 대한 자세한 내용은 모범 사례를 확인하세요.
섬의 퍼시스턴스 데이터 리셋하기
섬의 퍼시스턴스 데이터를 강제로 리셋해야 하는 경우, 플레이어가 섬에 합류했을 때 Verse에서 퍼시스턴스 데이터의 기본값을 플레이어의 weak_map에 할당하는 방식으로 리셋할 수 있습니다.
플레이어의 데이터가 이미 리셋되었는지 여부를 파악하려면 클래스의 버전 값을 포함하고, 퍼시스턴스 데이터의 일부인 새로운 변경사항으로 업데이트하면 됩니다. 이는 아래에 나와 있는 모범 사례 중 하나이니, 다른 사례들도 확인해 보세요!
Verse의 퍼시스턴스 타입
모듈 스코프 weak_map 변수에서 사용할 수 있는 퍼시스턴스 타입은 다음과 같습니다.
| Type | 설명 |
|---|---|
array | 배열의 엘리먼트 타입이 퍼시스턴스인 경우, 배열은 퍼시스턴스입니다. |
char32 | 문자 값은 퍼시스턴스입니다. |
char8 | 문자 값은 퍼시스턴스입니다. |
class | 클래스는 다음과 같은 경우 퍼시스턴스입니다. |
컬러 값은 퍼시스턴스입니다. | |
enum | 열거형은 퍼시스턴스 지정자로 정의된 경우 퍼시스턴스입니다. |
float | 부동 소수점 값은 퍼시스턴스입니다. |
int | 인티저 값은 퍼시스턴스입니다. |
logic | 로직 값은 퍼시스턴스입니다. |
map | 키 및 값 타입이 모두 퍼시스턴트 가능일 때 맵이 퍼시스턴트 가능합니다. |
option | 값이 퍼시스턴스인 옵션은 퍼시스턴스입니다. |
struct | 구조체는 다음과 같은 경우 퍼시스턴스입니다.
일단 섬을 퍼블리싱한 후에는 퍼시스턴스 구조체를 변경할 수 없습니다. 따라서 스키마가 일정하다고 알려진 경우에만 퍼시스턴스 구조체를 사용하는 것이 좋습니다. tuple(튜플) |
tuple | 모든 엘리먼트 타입이 퍼시스턴스인 튜플은 퍼시스턴스입니다. |
Vector2 값은 퍼시스턴스입니다. | |
Vector2i 값은 퍼시스턴스입니다. | |
Vector3 값은 퍼시스턴스입니다. |
퍼시스턴스 데이터로 테스트하기
섬의 최신 버전을 퍼블리싱하기 전에 퍼시스턴스 데이터 비헤이비어를 테스트하고 싶다면, 섬 설정 장치에서 퍼시스턴스 비헤이비어(Persistence Behavior): 플레이테스트 세션(Playtest Session) 세팅 및 퍼시스턴스 비헤이비어(Persistence Behavior): 편집 세션(Edit Session) 세팅에서 다음과 같은 비헤이비어를 설정할 수 있습니다.
| 퍼시스턴스 데이터 비헤이비어 | 설명 |
|---|---|
라이브 데이터에서 임포트(Import From Live) | 라이브 데이터를 사용할 수 있는 경우 라이브 데이터에서 세션 데이터를 임포트합니다. 섬이 라이브로 퍼블리싱되었으며, 플레이어가 섬의 라이브 버전에서 플레이한 상태여야 합니다. 라이브 데이터를 사용할 수 있는 경우 플레이테스트 세션 데이터가 라이브 데이터의 사본으로 시드됩니다. 섬 로직 변경과 연관된 퍼시스턴스 데이터 문제로 인해 테스트하려는 경우 매우 유용합니다. |
신규 사용자 시뮬레이션(Simulate New User) | 플레이어가 섬을 처음으로 플레이하는 것처럼 새 퍼시스턴스 데이터로 시작합니다. |
퍼시스턴스 데이터 비헤이비어 세팅은 플레이테스트 시 적용됩니다. 퍼시스턴스 데이터로 테스트할 수 있는 2가지 서로 다른 시나리오가 있습니다.
편집 세션: 퍼시스턴스 데이터 비헤이비어 세팅이 UEFN에서 세션을 시작할 때 적용됩니다. 즉, 퍼시스턴스 데이터가 단일 세션 내 다수의 게임에 걸쳐 유지될 수 있습니다. 세션을 종료하고 새 세션을 재시작하는 경우, 퍼시스턴스 데이터가 리셋되고 퍼시스턴스 데이터 비헤이비어 세팅이 다시 적용됩니다.
플레이테스트 세션: 퍼시스턴스 데이터 비헤이비어 세팅은 크리에이터 포털에서 플레이테스트를 구성한 경우, 플레이테스터가 플레이테스트 코드 또는 프라이빗 링크 코드 중 하나를 통해 합류할 때 적용됩니다. 퍼시스턴스 데이터 비헤이비어 세팅은 플레이어가 처음 합류할 때만 적용됩니다. 플레이어가 플레이테스트를 떠났다가 다시 합류하면, 플레이어의 데이터는 여러 세션에 걸쳐 유지되며 퍼시스턴스 데이터 비헤이비어 세팅은 다시 적용되지 않습니다. 퍼시스턴스 데이터를 리셋하려면 새 플레이테스트 링크 코드를 생성해야 합니다.
퍼시스턴스 데이터 관리 및 업데이트 방식에 영향을 미치는 섬 업데이트의 경우, UEFN에서 세션을 시작하는 시나리오와 링크 코드를 사용하여 플레이테스트하는 시나리오 둘 모두에서 테스트해 보는 것이 좋습니다. 라이브 데이터와 시뮬레이션된 신규 사용자 데이터 둘 모두로 퍼시스턴스 데이터에 적용한 변경 사항을 테스트해야 합니다. 이렇게 하면 섬의 현재 플레이어와 신규 플레이어 둘 모두에게 업데이트가 적용되도록 하는 데 도움이 됩니다.
섬의 신규 버전 퍼블리싱으로 인한 영향
섬이 퍼블리싱된 후 플레이어의 데이터가 weak_map에 저장될 때 플레이어의 퍼시스턴스 기록이 생성됩니다. 그런 다음 이 데이터가 저장되어 다음에 섬을 방문할 때 로드됩니다.
섬의 신규 버전이 퍼블리싱되면 퍼시스턴스 데이터가 신규 버전에 자동으로 병합됩니다. 자세한 내용은 섬의 퍼블리싱 버전 간에 데이터 수정하기를 참고하세요.
퍼블리싱된 섬의 롤백으로 인한 영향
크리에이터 포털을 통해 섬을 이전 버전으로 롤백하는 경우, 모든 사용자의 퍼시스턴스 데이터가 리셋됩니다.
플레이어에게 플레이어 데이터가 롤백의 영향을 받았음을 알리는 기능은 현재 지원되지 않습니다.
이로 인해 최근에 이루어진 플레이어 데이터 업데이트가 손실될 수 있으며, 심지어 플레이어 데이터가 완전히 리셋될 수도 있습니다. 롤백에 내부적으로 퍼시스턴스 데이터에 영향을 미칠 수 있는 로직 변경이 포함되지 않는 경우에도 마찬가지입니다.
퍼시스턴스 데이터에 미치는 영향으로 인해, 롤백 기능은 최후의 보루로만 사용하는 것이 좋습니다.
제한 사항
Verse에서 퍼시스턴스 데이터 작업 시 제한 사항은 다음과 같습니다.
최대 퍼시스턴스 오브젝트 크기
플레이어당 weak_map에 저장할 수 있는 데이터의 양에는 한도가 존재합니다.
weak_map 기록은 단일 weak_map 엘리먼트와 연관된 데이터의 총량입니다. 단일 weak_map 기록에서 최대 데이터 크기는 플레이어당 256킬로바이트(KB)입니다.
'weak_map' 값이 저장될 때 데이터 저장에 필요한 메모리 총량이 계산됩니다.
다음은 256KB 한도에 도달할 수도 있는 데이터의 몇 가지 예시입니다.
float또는int값 약 24,000개텍스트 약 200,000자 이는 평균적인 소설의 본문 약 60페이지에 해당합니다.
플레이어 기록에 256KB보다 큰 데이터를 저장하려고 시도하는 경우, 저장에 실패하고 Verse 런타임 오류가 발생합니다.
FitsInPlayerMap Verse 헬퍼 함수를 사용하여 저장 실패를 방지할 수 있습니다. FitsInPlayerMap 함수는 저장하고자 하는 기록의 사본을 받아 크기를 확인합니다. 기록이 저장 가능한 경우 함수 호출에 성공하고, 기록이 너무 큰 경우 실패합니다.
FitsInPlayerMap 함수는 데이터의 동적 array 또는 map 새 엘리먼트를 추가할 때 특히 유용합니다. 이전에 퍼시스턴스 기록에 있던 int, float 또는 logic을 업데이트해도 퍼시스턴스 기록의 크기가 변경되지 않습니다.
섬당 최대 퍼시스턴스 플레이어 Weak 맵
하나의 섬에는 최대 네 개의 퍼시스턴스 변수가 존재할 수 있습니다. 즉, player가 있는 네 개의 weak_map 변수를 키 타입으로 사용합니다. 이러한 요건은 Verse 컴파일러에 의해 강제됩니다.
클래스 타입의 Weak 맵 필요
최대 퍼시스턴스 변수 한도에 도달한 경우, 최소 하나의 퍼시스턴스 변수 weak_map 값이 클래스여야 합니다. 이는 다음 섬 퍼블리싱 시 이전 버전과의 호환성을 충족하는 한편, 변수에 추후 더 많은 데이터가 추가되도록 하기 위해서입니다.