> ## 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.

# Game Saves 離線模式

> 使用 PlayFab Game Saves 離線模式，讓玩家在沒有連線的情況下繼續遊戲進度，並在網路恢復後同步雲端存檔。

Game Saves 的設計可同時在線上和離線運作，即使無法使用網路連線，玩家也能繼續遊玩。系統會根據網路可用性和使用者的選擇，以兩種不同的模式運作。

## 連線模式

### 已連線至雲端模式

當網路可用且 `PFGameSaveFilesAddUserWithUiAsync()` 成功完成時，系統會以已連線至雲端模式運作。在此模式中：

* 所有 API 都能正常運作，並具備完整的雲端同步
* 存檔資料上傳如預期般運作
* 可取得儲存空間配額資訊
* 作用中裝置監視正常運作

### 離線模式 (未連線至雲端)

當網路無法使用或使用者選擇離線遊玩時，系統會進入功能有限的離線模式。您可以使用 `PFGameSaveFilesIsConnectedToCloud()` 檢查目前的連線狀態，以判斷系統正以哪種模式運作。

## 處理初始同步期間的網路失敗

在沒有網路連線的情況下呼叫 `PFGameSaveFilesAddUserWithUiAsync()` 時，會觸發 `PFGameSaveFilesUiSyncFailedCallback`。在系統等候使用者回應期間，`XAsyncBlock` 回呼不會觸發。非同步作業會暫停，直到使用者選取最終動作為止。

```cpp theme={null}
// Handle sync failure callback
void MyPFGameSaveFilesUiSyncFailedCallback(PFLocalUserHandle localUserHandle, PFGameSaveFilesSyncState syncState, HRESULT error, void* context)
{
    // Tell the user something like this:
    std::cout << "We couldn't sync your data with the cloud just now" << std::endl;
    std::cout << "Try syncing again or use this game offline" << std::endl;
    std::cout << "[Try Again]" << std::endl;
    std::cout << "[Use Offline]" << std::endl;

    // if user chooses [Try Again], call PFGameSaveFilesSetUiSyncFailedResponse(localUserHandle, PFGameSaveFilesUiSyncFailedUserAction::Retry);
    // if user chooses [Use Offline], call PFGameSaveFilesSetUiSyncFailedResponse(localUserHandle, PFGameSaveFilesUiSyncFailedUserAction::UseOffline);

    // These API calls can happen inside or outside of this callback
}
```

**使用者回應選項：**

* **再試一次 (`Retry`)**：重試網路呼叫。如果重試也失敗，此回呼會再次觸發，使用者必須再次回應。在每次重試迴圈中，`XAsyncBlock` 回呼都會保持延遲。
* **離線使用 (`UseOffline`)**：`XAsyncBlock` 回呼會以 `S_OK` 觸發，但系統會進入離線模式 (可使用 `PFGameSaveFilesIsConnectedToCloud()` 偵測)。
* **取消**：`XAsyncBlock` 回呼會以 `E_PF_GAMESAVE_USER_CANCELLED` 觸發。

## 離線模式中的 API 行為

在離線模式中，API 的行為會有所不同：

### 正常運作的 API

* `PFGameSaveFilesGetFolder()` - 傳回本機存檔資料夾路徑

### 功能有限的 API

* `PFGameSaveFilesUploadWithUiAsync()` - 立即傳回 `S_OK`，但非同步完成時會傳回 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD`
* `PFGameSaveFilesGetRemainingQuota()` - 傳回 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD`
* `PFGameSaveFilesSetActiveDeviceChangedCallback()` - 可以設定，但永遠不會觸發

### 返回線上模式

* 再次呼叫 `PFGameSaveFilesAddUserWithUiAsync()` 以嘗試重新連線
* 不需要完全重新初始化 Game Saves 系統
* 如果網路仍無法使用，會再次顯示失敗 UI
* 在重試之後，使用 `PFGameSaveFilesIsConnectedToCloud()` 確認連線狀態

## Game Saves 何時會進入離線模式或傳回錯誤

常見的整合問題是：*初始同步 (`PFGameSaveFilesAddUserWithUiAsync`) 何時會讓玩家進入離線模式，何時會以錯誤碼失敗？* 共有三種最終結果 (已連線、離線或已取消)，而取消可能來自玩家或遊戲：

| 結果 | 達成方式 | 非同步結果 | `IsConnectedToCloud()` | 是否有存檔資料夾？ | 建議處理方式 |
| - | - | - | - | - | - |
| **已連線** | 同步成功完成 | `S_OK` | `true` | 是 | 允許遊玩；存檔會同步至雲端。 |
| **離線** | 使用者在同步失敗提示中選取 **Use Offline** (或另一部裝置成為作用中裝置) | `S_OK` | `false` | 是 | 允許使用本機存檔遊玩；告知玩家存檔不會同步。 |
| **由玩家取消** | 使用者在任何提示中選取 **Cancel** | `E_PF_GAMESAVE_USER_CANCELLED` (`0x800704C7`) | 不適用 | **否** | **封鎖遊玩**或返回安全的功能表——沒有可儲存或載入的資料夾。 |
| **由遊戲取消** | 遊戲對 `XAsyncBlock` 呼叫了 `XAsyncCancel` | `E_ABORT` (`0x80004004`) | 不適用 | **否** | 與玩家取消相同——沒有可儲存或載入的資料夾。 |

重點：

* **離線模式是成功的結果，而不是錯誤。** 只有在明確選擇 **Use Offline** 時才會進入此模式，且非同步作業會以 `S_OK` 完成。請使用 `PFGameSaveFilesIsConnectedToCloud()` 偵測此模式。
* **暫時性/技術性失敗會透過同步失敗 UI 呈現**，而不是直接從 `PFGameSaveFilesAddUserWithUiAsync` 傳回。接著，使用者 (或您的自動回應) 會選擇 `Retry`、`UseOffline` 或 `Cancel`，最後解析為上述三種結果之一。
* **取消是最終結果，且不會產生存檔資料夾。** 請將「已取消」(或任何未留下資料夾的失敗) 視為*不允許遊玩*。
* **玩家取消和遊戲取消會傳回不同的代碼。** 只有玩家在提示中選擇 **Cancel** 才會產生 `E_PF_GAMESAVE_USER_CANCELLED`。如果您的遊戲自行使用 `XAsyncCancel` 取消作業，則會以 `E_ABORT` 完成。如果您想以相同方式處理兩者，請同時檢查兩者。

<Note>
  取消**衝突**提示也是最終結果。它會以 `E_PF_GAMESAVE_USER_CANCELLED` 完成，且不會自動轉到同步失敗的「Use Offline」提示。如果您想要「拒絕衝突但繼續離線遊玩」的體驗，請明確設計 (例如，重新執行 `PFGameSaveFilesAddUserWithUiAsync`，並在產生的失敗中選取 Use Offline)。請參閱 [Game Saves 衝突](/zh-TW/services/playfab/player-progression/game-saves/conflicts)。
</Note>

## Game Saves 錯誤碼

下列 HRESULT 由 Game Saves SDK 定義。`0x8923xxxx` 範圍內的代碼為 Game Saves 專用；`0x800704C7` 為 `HRESULT_FROM_WIN32(ERROR_CANCELLED)`。

| 代碼 | 值 | 傳回時機 |
| - | - | - |
| `E_PF_GAMESAVE_USER_CANCELLED` | `0x800704C7` | 使用者在任何 UI 提示中選取 **Cancel**。最終結果；沒有存檔資料夾。(如果遊戲使用 `XAsyncCancel` 取消 `XAsyncBlock`，作業會改以標準的 `E_ABORT` (`0x80004004`) 完成。) |
| `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` | `0x89237004` | 當工作階段處於離線模式時，由 `PFGameSaveFilesUploadWithUiAsync()` 和 `PFGameSaveFilesGetRemainingQuota()` 傳回。 |
| `E_PF_GAMESAVE_NETWORK_FAILURE` | `0x89237005` | 在仍連線至雲端的情況下發生暫時性網路失敗後，由 `PFGameSaveFilesUploadWithUiAsync()` 傳回。可以安全地稍後重試。 |
| `E_PF_GAMESAVE_DEVICE_NO_LONGER_ACTIVE` | `0x89237007` | 當此裝置不再是作用中裝置 (另一部裝置已接手) 時，由 `PFGameSaveFilesUploadWithUiAsync()` 傳回。 |
| `E_PF_GAMESAVE_DISK_FULL` | `0x89237008` | 本機磁碟空間不足，無法下載存檔資料。請提示使用者釋放空間並重試。 |
| `E_PF_GAMESAVE_OPERATION_IN_PROGRESS` | `0x89237009` | 此使用者已有衝突的作業正在執行：在另一個上傳或雲端重設進行中時呼叫了 `PFGameSaveFilesUploadWithUiAsync()`、在雲端重設進行中時呼叫了 `PFGameSaveFilesAddUserWithUiAsync()`，或在另一個重設、上傳或下載進行中時呼叫了 `PFGameSaveFilesResetCloudAsync()`。未開始或修改任何內容；請等候進行中的作業完成，然後重試。從 October 2026 GDK (2610) 開始提供。 |
| `E_PF_GAMESAVE_LOCAL_FILE_UNAVAILABLE` | `0x8923700A` | 當上傳期間無法讀取本機存檔檔案時 (例如，遊戲仍開啟該檔案用於寫入)，由 `PFGameSaveFilesUploadWithUiAsync()` 傳回。未將任何內容認可至雲端。暫時性：在遊戲停止寫入該檔案後重試。在 October 2025 GDK (2510) QFE5、April 2026 GDK (2604) QFE6 和 October 2026 GDK (2610) 中提供。 |
| `E_PF_GAMESAVE_DOWNLOAD_IN_PROGRESS` | `0x89237006` | 在 `PFGameSaveFilesAddUserWithUiAsync()` 完成初始同步之前呼叫了 `PFGameSaveFilesUploadWithUiAsync()`。 |
| `E_PF_GAMESAVE_USER_NOT_ADDED` | `0x89237003` | 在該使用者的 `PFGameSaveFilesAddUserWithUiAsync()` 完成之前呼叫了 API。 |
| `E_PF_GAMESAVE_USER_ALREADY_ADDED` | `0x89237002` | 對已新增的使用者再次呼叫了 `PFGameSaveFilesAddUserWithUiAsync()`。 |
| `E_PF_GAMESAVE_ALREADY_INITIALIZED` | `0x89237001` | 呼叫了兩次 `PFGameSaveFilesInitialize()`，中間沒有呼叫 `PFGameSaveFilesUninitializeAsync()`。 |
| `E_PF_GAMESAVE_NOT_INITIALIZED` | `0x89237000` | 在 `PFGameSaveFilesInitialize()` 之前呼叫了 API。 |

如需了解這些結果在內建 (處理程序外) 系統 UI 與您自己的回呼之間如何產生，請參閱 [Game Saves UI 回呼](/zh-TW/services/playfab/player-progression/game-saves/ui-callbacks#in-process-vs-out-of-process-system-ui)。

## 其他連線狀態情境

`PFGameSaveFilesIsConnectedToCloud()` API 特別有用，因為中斷連線可能以多種方式發生：

* **同步期間網路無法使用**：使用者明確選擇離線遊玩
* **作用中裝置已變更**：另一部裝置接手成為作用中裝置，自動將此裝置置於離線模式

請在嘗試雲端作業之前使用此 API，以提供適當的使用者意見反應。

## 離線支援的最佳做法

1. **一律實作同步失敗回呼**，以妥善處理網路問題
2. 在嘗試雲端作業之前，使用 `PFGameSaveFilesIsConnectedToCloud()` **定期檢查連線狀態**
3. 在離線模式下運作時**通知玩家**，讓他們了解存檔不會同步
4. 在網路連線恢復時**提供重試選項**
5. **本機存檔一律可運作** - 無論網路狀態為何，玩家都能繼續遊玩
6. **監視中斷連線** - 請記住，當另一部裝置變成作用中時，裝置可能會中斷連線

## 已連線模式中的上傳行為

即使在已連線模式中，上傳也可能因網路問題或速率限制而失敗。發生這種情況時，`XAsyncBlock` 回呼不會立即觸發。當系統透過 [UI 回呼狀態機](/zh-TW/services/playfab/player-progression/game-saves/ui-callbacks#how-the-state-machine-works)等候使用者回應時，非同步作業會暫停：

1. `PFGameSaveFilesUiSyncFailedCallback` 會附帶錯誤詳細資料觸發。
2. `XAsyncBlock` 回呼尚未觸發。在系統等候回應期間，作業會暫停。
3. 如果使用者選取 `Retry`，上傳會重試。如果再次失敗，回呼會再次觸發，使用者必須再次回應。
4. 如果使用者選取 `Cancel`，`XAsyncBlock` 回呼會以 `E_PF_GAMESAVE_USER_CANCELLED` 觸發。
5. 如果重試成功，`XAsyncBlock` 回呼會以 `S_OK` 觸發。

遊戲可以在網路恢復後再次呼叫 `PFGameSaveFilesUploadWithUiAsync()`。

<Note>
  **在處理程序內，上傳執行期間請勿在同步失敗提示中提供 `Use Offline`。** 上傳會觸發與初始同步相同的 `PFGameSaveFilesUiSyncFailedCallback`，因此 SDK 不會限制選項。但是，如果您的遊戲以 `UseOffline` 回應上傳失敗，上傳會以 `E_ABORT` 失敗 (且偵錯組建會觸發判斷提示)。請只在該處提供 `Retry` 和 `Cancel`。
</Note>

## 上傳何時會使工作階段離線

上傳通常不會變更連線模式，但在下列情況中，可能會以工作階段離線結束。在每種情況下，上傳都會以 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` 完成，之後 `PFGameSaveFilesIsConnectedToCloud()` 會傳回 `false`。

* **工作階段原本就處於離線狀態。** 上傳不會執行，並以 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` 完成，即使網路已恢復亦然。
* **雲端有較新的存檔。** 如果服務在上傳完成時回報已從另一部裝置認可較新的存檔，Game Saves 會將工作階段置於離線狀態、觸發作用中裝置變更回呼，並以 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` 完成上傳。
* **玩家在重新鎖定提示中選擇 `Use Offline`。** 如果先前的上傳已認可其資料但之後失敗，下一次上傳必須先重新取得存檔鎖定。在該步驟期間出現的同步失敗提示可以用 `UseOffline` 回應，這會使工作階段離線，並以 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` 完成上傳。

若要重新連線，請再次呼叫 `PFGameSaveFilesAddUserWithUiAsync()`。

## 取消上傳

上傳可以用與初始同步相同的方式取消：使用者可以在上傳進行中時 `Cancel` **進度** UI，或在上傳遇到錯誤時 `Cancel` **同步失敗**提示。無論哪種方式，`PFGameSaveFilesUploadWithUiAsync()` 都會以 `E_PF_GAMESAVE_USER_CANCELLED` (`0x800704C7`) 完成，且存檔不會上傳。其最終結果為**成功**、**已取消**或**失敗** (其中 `E_PF_GAMESAVE_DISCONNECTED_FROM_CLOUD` 表示工作階段現在處於離線狀態；請參閱[上傳何時會使工作階段離線](#when-an-upload-takes-the-session-offline))。請將 `E_PF_GAMESAVE_USER_CANCELLED` 與其他失敗分開處理，以便區分「玩家已退出」和「上傳發生錯誤」。如果您的遊戲自行使用 `XAsyncCancel` 取消上傳，則會以 `E_ABORT` 完成，而不是 `E_PF_GAMESAVE_USER_CANCELLED`。


## Related topics

- [Game Saves 快速入門](/zh-TW/services/playfab/player-progression/game-saves/quickstart.md)
- [Game Saves UI 回呼](/zh-TW/services/playfab/player-progression/game-saves/ui-callbacks.md)
- [Game Saves 錯誤處理常見問題集](/zh-TW/services/playfab/player-progression/game-saves/error-handling-faq.md)
- [處理離線遊戲的最佳做法](/zh-TW/services/xbox-services/develop/best-practices/live-best-practices-offline-play.md)
- [XBOX 服務使用者權限的用戶端使用](/zh-TW/services/xbox-services/fundamentals/identity/privileges/concepts/live-user-privileges-client.md)
