> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XGameSave API 概述

> 涵盖容器和 blob 模型、提供程序初始化、更新句柄、原子更新和同步流程图的 XBOX XGameSave API 参考。

本文介绍了容器和 blob 模型，并涵盖了提供程序初始化、提供程序关闭和更新句柄生命周期。文中概述了原子更新行为并附带了同步流程图。本文还提供了文件大小和配额约束，以及最佳实践和常见问题解答。

`XGameSave` API 使你能够管理 blob 和容器以管理游戏存档数据。我们推荐 Microsoft Game Development Kit (GDK) 标题的游戏存档使用 [XGameSaveFiles](/build/core-features/common/game-save/xgamesavefiles)。如果 `XGameSaveFiles` 不是一个选项，则使用 `XGameSave`。

有关 XGameSave 的系统 API 参考，请参阅 [XGameSave (API 内容)](/reference/system/xgamesave/xgamesave_members)。

以下术语在 `XGameSave` 中经常出现。

* **锁**：一种在用户当前使用的设备上，为特定用户授予对标题游戏存档独占访问权的机制。它确保在锁被持有时，没有其他设备可以修改该用户的游戏存档。
  * 例如，如果用户在设备 A 上玩标题 T，则 A 上具有该用户的标题 T 的锁。
* **提供程序**：与游戏存档系统通信并负责管理标题数据的中介进程。该提供程序还管理设备上用户的锁。
* **容器**：类似于文件夹。
* **Blob**：类似于单个文件。

## 提供程序管理

要获取存储空间，游戏必须初始化提供程序。连接后，标题通过调用 `XGameSaveInitializeProvider` 或 `XGameSaveInitializeProviderAsync` 尝试获取标题云存储的锁。

如果标题因连接丢失而未能从云端同步，请确定用户是否可以在离线模式下继续游玩。

当标题挂起或终止时，标题必须使用 [XGameSaveCloseProvider](/reference/system/xgamesave/functions/xgamesavecloseprovider) 关闭提供程序。该提供程序无法跨挂起-恢复边界重复使用。

<Note>此问题仅适用于 `XGameSave`。`XGameSaveFiles` 会自动关闭提供程序。</Note>

## 容器管理

为避免访问容器时的数据丢失（例如在同步完成前创建容器），请调用 `XGameSaveEnumerateContainerInfo` 或 `XGameSaveEnumerateContainerInfoByName` 以查看用户拥有的容器。

使用 `XGameSaveCreateContainer` 获取新的或现有容器的容器句柄。如果容器已存在，则提供其句柄。如果容器不存在，则创建新容器并提供其句柄。

使用 `XGameSaveDeleteContainer` 删除容器。该容器中的所有 blob 也会被删除。

为防止句柄泄漏，当容器不再使用时或标题挂起或终止时，使用 `XGameSaveCloseContainer` 关闭所有容器句柄。

## Blob 管理

通过调用 `XGameSaveCreateUpdate` 来操作容器内的数据。

以下详细信息概述了 `XGameSaveUpdate` 如何管理容器内的 blob 更改，以及每个更新如何被创建、修改和提交。

* 一个更新适用于一个容器。

* 一个更新最多可以写入 GS\_MAX\_BLOB\_SIZE (16 MB)。

* 单个更新中可以修改多个 blob。

* 每个更新只能对单个 blob 进行一次修改。

* 提交更新会消耗 `XGameSaveUpdate` 句柄。无论提交成功还是失败，都要关闭该句柄。

* 更新是原子的。如果其中任何部分失败，整个更新都会失败。

* `XGameSaveCreateUpdate` 创建一个更新上下文以存储所有的 blob 修改。

* `XGameSaveSubmitBlobWrite` 向新的或现有的 blob 写入数据，并且需要一个更新的上下文。

* `XGameSaveSubmitBlobDelete` 删除 blob。

* `XGameSaveSubmitUpdate` 提交更新上下文。

* `XGameSaveCloseUpdate` 关闭更新句柄。标题在每次提交后调用它以防止泄漏。

* 使用 `XGameSaveEnumerateBlobInfo` 或 `XGameSaveEnumerateBlobInfoByName` 访问容器中的所有 blob。

<Note>当数据以 XML 导出时，写入 blob 的数据以 `Base64` 表示。</Note>

## 实现

以下步骤显示了 `XGameSave` 实现的一般流程。

1. 在标题启动或恢复时，初始化提供程序。
2. 枚举和创建容器句柄。
3. 定期提交带有 blob 修改的 `XGameSaveUpdates`，并在提交时清理更新句柄。
4. 在标题挂起或终止时关闭容器和提供程序句柄。

<Info>在标题启动和恢复时调用 `XGameSaveInitializeProvider`。此调用可确保提供程序正确初始化并在标题运行时保持活动状态。如果不调用它，标题的行为可能不可预测。</Info>

### 代码示例

有关演示如何使用 `XGameSave` API 的代码示例，请参阅 [GameSaveCombo](https://learn.microsoft.com/samples/microsoft/xbox-gdk-samples/gamesavecombo/)。

## 游戏存档流程

以下是简化游戏存档流程的流程图。其说明如下。

<img src="https://mintcdn.com/microsoft-4404708b/UZTRJSf0emX1fheE/images/gdk/features/common/simple-sync-overview.png?fit=max&auto=format&n=UZTRJSf0emX1fheE&q=85&s=98c2d4bdfc034fdd8340c67e10c4d5e7" alt="简化游戏存档同步过程的流程图。" width="530" height="572" data-path="images/gdk/features/common/simple-sync-overview.png" />

### 标题启动

当用户启动或恢复标题时发生标题启动。

### 用户登录

标题启动用户登录。此调用也是你调用 `XGameSaveInitializeProvider` 的地方。
有关用户设置的更多信息，请参阅[用户模型](/build/core-features/common/game-save/game-saves-developer-guide#user-models)。

### 连接检查

标题确定它是否可以连接到 XBOX 网络。如果不能，则由你决定是否为标题启用[离线模式](/build/core-features/common/game-save/game-saves-syncing#connection-check)。

### 数据所有权检查

设备检查用户当前是否正在其他设备上游玩。对于特定标题，一次只能有一台设备访问该用户的数据。

### 与云同步数据

设备将游戏存档本地存储数据与云端同步。如果存在冲突，系统会通过冲突解决对话框提示用户。

对话框：[你想使用哪一个？](/build/core-features/common/game-save/game-saves-dialogues#which-one-do-you-want-to-use)

当设备上的数据比云端数据更新时，标题会提示用户在使用本地数据或云端数据之间进行选择。

### 游戏循环

标题可以自由地读写游戏存档本地存储。

### 游戏会话结束

游戏会话结束时，系统会自动尝试将数据上传到云端。请确保标题在其退出流程中调用 `XGameSaveUninitializeProvider`，以免留下已初始化的提供程序。有条不紊的关闭确保在退出之前干净地保存数据。

有关详细的同步信息，请参阅[理解游戏存档同步流程](/build/core-features/common/game-save/game-saves-syncing)。

## 限制和配额

### 限制

`XGameSaveUpdate` 将每个更新限制为 16 MB。因此，`XGameSave` 只能管理最大 16 MB 的单个文件更新。此限制与 `XGameSaveFiles` 不同，后者支持最大 64 MB 的文件。

### 配额

每个标题的用户最多可以保存 256 MB 的数据。使用 [XGameSaveGetRemainingQuota](/reference/system/xgamesave/functions/xgamesavegetremainingquota) 获取剩余配额。要为你的标题获取存储扩展，请联系你的开发者合作伙伴经理 (DPM)。

## 最佳实践

* 不要保存数据后立即查询并请求相同的数据。
* 跨容器的数据依赖不可靠。每个 `XGameSaveSubmitUpdate` 调用要么原子地应用所有更改，要么全部不应用。
* 每次更新调用中使用的 blob 越多，完成文件系统操作以存储数据所需的原子操作时间就越多。

## 常见问题解答

### 我正在升级我的游戏存档实现。正确的方法是什么？

使用 [XGameSaveFiles](/build/core-features/common/game-save/xgamesavefiles)。

### 我可以将 XGameSave 与 XGameSaveFiles 一起使用吗？

可以。但是，仅用于迁移。有关详细信息，请参阅 [XGameSave 与 XGameSaveFiles 之间的互操作性](/build/core-features/common/game-save/game-saves-walkthroughs-and-samples#interop-between-xgamesave-and-xgamesavefiles)。

### XGameSave 保存到什么文件路径？

**主机**：标题活动时提供临时路径。主机文件无法通过文件资源管理器访问。

**PC**：`%AppData%\Local\Packages\<PACKAGE_NAME>\SystemAppData\wgs\<HexXuid>_<SCID>\`

请注意，`XGameSave` 的 PC 路径与 `XGameSaveFiles` 不同。它使用 `xgs`。

### 我可以指定保存数据的路径吗？

可以，但仅限 PC。仅当你从另一个标题移植解决方案时才建议这种方法。此解决方案使用[无代码云存档](/build/core-features/common/game-save/game-saves-walkthroughs-and-samples#porting-previous-titles-to-pc-game-saves-with-no-code-cloud-saves)。

### 是否存在使用 Sync on Demand 的情况？

否。它是出于旧版支持原因而存在。

## 参考 API 文档

* [XGameSave (API 内容)](/reference/system/xgamesave/xgamesave_members)
  * 函数
    * [XGameSaveCloseProvider](/reference/system/xgamesave/functions/xgamesavecloseprovider)
    * [XGameSaveGetRemainingQuota](/reference/system/xgamesave/functions/xgamesavegetremainingquota)

## 另请参阅

[游戏存档目录](/build/core-features/common/game-save/game-saves-toc)


## Related topics

- [游戏存档概述](/zh-CN/build/core-features/common/game-save/game-saves-overview.md)
- [XGameSaveCloseProvider](/zh-CN/reference/system/xgamesave/functions/xgamesavecloseprovider.md)
- [XGameSaveGetRemainingQuota](/zh-CN/reference/system/xgamesave/functions/xgamesavegetremainingquota.md)
- [XGameSave](/zh-CN/reference/system/xgamesave/xgamesave_members.md)
- [XGameSaveFiles API 概述](/zh-CN/build/core-features/common/game-save/xgamesavefiles.md)
