상태 머신 작동 방식
Game Saves는 UI 콜백을 비동기 작업 수명 주기와 조정하기 위해 내부 상태 머신을 사용합니다. UI 콜백이 실행되면 비동기 작업이 일시 중지됩니다. 콜백이 해결될 때까지XAsyncBlock 콜백은 실행되지 않습니다. 게임이 해당 응답 API를 호출하거나 비동기 작업이 취소될 때까지 상태 머신은 진행되지 않습니다.
이는 다음을 의미합니다.
- 각 콜백 유형에는 해당하는 응답 API가 있습니다. 다음에 무엇을 할지 시스템에 알리려면 응답 API를 호출하세요.
- 응답 API는 콜백 함수 내부 또는 외부에서 호출할 수 있습니다.
- 응답 액션이
Retry인 경우 작업이 재시도되고 동일한 콜백을 다시 트리거할 수 있습니다. XAsyncBlock콜백은 작업이 종료 상태(성공, 취소 또는 오프라인 대체)에 도달한 후에만 실행됩니다.
PFGameSaveFilesUiSyncFailedCallback이 오류와 함께 실행됩니다.XAsyncBlock콜백은 아직 실행되지 않습니다. 상태 머신이 응답을 기다립니다.- 사용자가
Retry를 선택하고 재시도도 실패하면 동기화 실패 콜백이 다시 실행됩니다. - 사용자가
Cancel을 선택하면XAsyncBlock콜백이E_PF_GAMESAVE_USER_CANCELLED로 실행됩니다. - 재시도가 성공하면
XAsyncBlock콜백이S_OK로 실행됩니다.
콜백이 트리거되는 시점
UI 콜백은 두 가지 비동기 작업 중에만 실행됩니다.콜백 등록
PFGameSaveFilesAddUserWithUiAsync 또는 PFGameSaveFilesUploadWithUiAsync를 호출하기 전에 모든 콜백을 등록하세요.
콜백 참조
Progress
업로드 또는 다운로드 진행 상황을 보고합니다. 콜백 내부에서PFGameSaveFilesUiProgressGetProgress를 사용하여 현재 PFGameSaveFilesSyncState, 완료된 바이트 및 전체 바이트를 검색합니다.
콜백: PFGameSaveFilesUiProgressCallback
응답 API: PFGameSaveFilesSetUiProgressResponse
진행률 콜백은 계속 진행하기 위해 응답이 필요하지 않습니다. 작업은 자체적으로 계속 진행됩니다. 사용자가 취소하려는 경우에만 응답 API를 호출하세요.
동기화 상태
PFGameSaveFilesSyncState 열거형은 작업이 어느 단계에 있는지를 나타냅니다.
Sync failed
예를 들어 네트워크 문제나 속도 제한으로 인해 동기화 작업이 실패할 때 실행됩니다. 콜백:PFGameSaveFilesUiSyncFailedCallback
매개 변수: PFGameSaveFilesSyncState(실패한 단계)와 HRESULT(오류 코드)를 받습니다.
응답 API: PFGameSaveFilesSetUiSyncFailedResponse
오프라인 모드 동작에 대한 자세한 내용은 Game Saves 오프라인 모드를 참조하세요.
Active device contention
이 사용자에 대해 다른 디바이스가 이미 활성 디바이스인 경우PFGameSaveFilesAddUserWithUiAsync 중에 실행됩니다. 콜백은 로컬 및 원격 세이브 데이터 모두에 대한 PFGameSaveDescriptor 구조체를 받으며, 여기에는 사용자의 결정을 돕기 위해 표시할 수 있는 디바이스 이름, 타임스탬프 및 세이브 크기가 포함됩니다.
콜백: PFGameSaveFilesUiActiveDeviceContentionCallback
응답 API: PFGameSaveFilesSetUiActiveDeviceContentionResponse
활성 디바이스 동작에 대한 자세한 내용은 Game Saves 활성 디바이스 변경을 참조하세요.
Conflict
로컬 세이브 데이터와 클라우드 세이브 데이터가 서로 달라진 경우PFGameSaveFilesAddUserWithUiAsync 중에 실행됩니다. 콜백은 로컬 및 원격 세이브 데이터 모두에 대한 PFGameSaveDescriptor 구조체를 받습니다.
콜백: PFGameSaveFilesUiConflictCallback
응답 API: PFGameSaveFilesSetUiConflictResponse
충돌 해결은 개별 파일이나 폴더가 아니라 세이브 전체에 적용됩니다. 원자 단위 수준에서 충돌이 감지되고 전역적으로 해결되는 방식에 대한 자세한 내용은 Game Saves 충돌을 참조하세요.
Out of storage
로컬 디바이스에 클라우드에서 세이브 데이터를 다운로드할 디스크 공간이 충분하지 않은 경우PFGameSaveFilesAddUserWithUiAsync 중에 실행됩니다. 콜백은 필요한 공간을 나타내는 requiredBytes를 받습니다.
콜백: PFGameSaveFilesUiOutOfStorageCallback
응답 API: PFGameSaveFilesSetUiOutOfStorageResponse
In-process 및 Out-of-process(시스템 UI) 비교
Game Saves가 실행되는 위치는 플랫폼에 따라 다르며, 이는 UI 이벤트가 처리되는 방식에 영향을 줍니다.- Out-of-process(XBOX 및 Windows): XBOX와 Windows에서 Game Saves는 항상 out-of-process로 실행됩니다. 플랫폼(Connected Storage / GRTS)이 동기화를 수행하고 동기화 실패, 충돌, 활성 디바이스 경합 및 저장 공간 부족에 대한 기본 제공 시스템 UI 대화 상자를 제공합니다. 플레이어는 해당 대화 상자와 직접 상호 작용하며, 플랫폼은 그 결과를 게임이 in-process에서 받는 것과 동일한 비동기 완료 코드로 변환합니다. 기본 제공 UI를 대체하기 위해 여전히 콜백을 등록할 수 있습니다.
- In-process(Steam Deck 같은 기타 플랫폼): 플랫폼 서비스를 사용할 수 없는 경우 게임이 Game Saves 동기화 엔진을 호스트하고 위에서 설명한 콜백을 통해 UI 이벤트를 처리합니다. 게임이 응답 API를 사용하여 상태 머신을 완전히 구동합니다.
취소는 항상 가능한 결과입니다
경로와 관계없이 모든 UI 흐름은 동기화가 성공하지 않은 채 사용자가 취소하는 것으로 끝날 수 있으므로, 게임은 항상 종료 취소를 처리해야 합니다.
플레이어가 계속 플레이할 수 있는 유일한 “취소” 액션은 동기화 실패 프롬프트의 Use Offline(성공 결과)입니다. 그 밖의 모든 Cancel은 종료 결과이며 세이브 폴더를 남기지 않습니다. 플레이를 허용하지 않음으로 처리하세요. Game Saves 오프라인 모드를 참조하세요.
기본 제공(out-of-process) 시스템 UI에서는 이러한 선택지가 플랫폼 문구로 표시됩니다. 예를 들어 동기화 실패 대화 상자는 “Try again” / **“Play offline”**을, 경합 대화 상자는 “Stop sync & continue” / **“Quit game”**을 제공합니다. “Play offline”은 오프라인 모드(
S_OK, 연결되지 않음)에 해당하고, “Quit game”은 E_PF_GAMESAVE_USER_CANCELLED에 해당합니다.
충돌 프롬프트를 취소하는 것은 두 경로 모두에서 종료 결과입니다. E_PF_GAMESAVE_USER_CANCELLED로 완료되며 동기화 실패 프롬프트로 이어지지 않습니다.
사용자 지정 크로스 플랫폼 UI(예: Steam Deck 구현과 일치시키는 경우)를 사용하려면 모든 곳에 콜백을 등록하고 대상 하드웨어에서 out-of-process 흐름을 검증하세요. 경로와 관계없이 완료 결과에 따라 플레이를 제어하세요. S_OK + 연결됨 → 온라인으로 플레이, S_OK + 연결되지 않음 → 오프라인으로 플레이(플레이어에게 경고), 폴더 없이 취소/실패 → 플레이 차단.
플랫폼 요구 사항
Steam Deck 구현에 대한 자세한 내용은 Steam Deck 구현 가이드를 참조하세요.
