状态机的工作原理
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 之前注册所有回调:
回调参考
进度
报告上传或下载进度。在回调内使用PFGameSaveFilesUiProgressGetProgress 检索当前的 PFGameSaveFilesSyncState、已完成的字节数和总字节数。
回调:PFGameSaveFilesUiProgressCallback
响应 API:PFGameSaveFilesSetUiProgressResponse
进度回调不需要响应即可继续。操作会自行继续进行。仅在用户想要取消时才调用响应 API。
同步状态
PFGameSaveFilesSyncState 枚举指示操作处于哪个阶段:
同步失败
当同步操作失败时触发,例如由于网络问题或速率限制。 回调:PFGameSaveFilesUiSyncFailedCallback
参数:接收 PFGameSaveFilesSyncState(失败的阶段)和 HRESULT(错误代码)。
响应 API:PFGameSaveFilesSetUiSyncFailedResponse
有关离线模式行为的更多详细信息,请参阅Game Saves 离线模式。
活动设备争用
在PFGameSaveFilesAddUserWithUiAsync 期间,当另一台设备已经是该用户的活动设备时触发。回调接收本地和远程存档数据的 PFGameSaveDescriptor 结构,其中包括可以显示以帮助用户做出决定的设备名称、时间戳和存档大小。
回调:PFGameSaveFilesUiActiveDeviceContentionCallback
响应 API:PFGameSaveFilesSetUiActiveDeviceContentionResponse
有关活动设备行为的更多详细信息,请参阅Game Saves 活动设备变更。
冲突
在PFGameSaveFilesAddUserWithUiAsync 期间,当本地和云存档数据发生分歧时触发。回调接收本地和远程存档数据的 PFGameSaveDescriptor 结构。
回调:PFGameSaveFilesUiConflictCallback
响应 API:PFGameSaveFilesSetUiConflictResponse
冲突解决适用于整个存档,而非单个文件或文件夹。有关如何在原子单元级别检测冲突并在全局范围内解决的详细信息,请参阅Game Saves 冲突。
存储空间不足
在PFGameSaveFilesAddUserWithUiAsync 期间,当本地设备没有足够的磁盘空间从云端下载存档数据时触发。回调接收 requiredBytes,指示所需的空间量。
回调:PFGameSaveFilesUiOutOfStorageCallback
响应 API:PFGameSaveFilesSetUiOutOfStorageResponse
进程内与进程外(系统 UI)
Game Saves 的运行位置取决于平台,这会影响 UI 事件的处理方式:- 进程外(XBOX 和 Windows):在 XBOX 和 Windows 上,Game Saves 始终在进程外运行。平台(Connected Storage / GRTS)执行同步,并针对同步失败、冲突、活动设备争用和存储空间不足提供内置系统 UI 对话框。玩家直接与这些对话框交互,平台会将结果转换回与您的游戏在进程内模式下收到的相同的异步完成代码。您仍然可以注册回调来替换内置 UI。
- 进程内(其他平台,例如 Steam Deck):在平台服务不可用的情况下,您的游戏托管 Game Saves 同步引擎,并通过上述回调处理 UI 事件。您的游戏通过响应 API 完全驱动状态机。
取消始终是可能的结果
无论采用哪种路径,每个 UI 流程都可能以用户在未成功同步的情况下退出而结束,因此您的游戏必须始终处理最终的取消:
唯一仍允许玩家继续的“退出”操作是在同步失败提示中选择 Use Offline(一种成功结果)。其他所有取消都是最终结果,且不会留下存档文件夹。请将其视为不允许游玩。请参阅 Game Saves 离线模式。
在内置(进程外)系统 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 实现保持一致),请在所有平台上注册回调,并在目标硬件上验证进程外流程。无论采用哪种路径,都应根据完成结果控制游玩:S_OK + 已连接 → 在线游玩;S_OK + 未连接 → 离线游玩(警告玩家);取消/失败且无文件夹 → 阻止游玩。
平台要求
有关 Steam Deck 实现的详细信息,请参阅 Steam Deck 实现指南。
