Google 登入 API 淘汰後,我們將於 2026 年移除遊戲服務第 1 版 SDK。2025 年 2 月後,新整合遊戲服務第 1 版 SDK 的遊戲將無法在 Google Play 發布,建議改用遊戲服務第 2 版 SDK。
雖然整合舊版遊戲第 1 版的現有遊戲仍可運作幾年,但我們建議您自 2025 年 6 月起遷移至第 2 版。
本指南適用於 Play 遊戲服務第 1 版 SDK。Play 遊戲服務第 2 版的 C++ SDK 尚未推出。
本指南說明如何在 C++ 應用程式中使用遊戲進度存檔服務,儲存及載入玩家的遊戲進度資料。您可以使用這項服務,在遊戲過程中隨時自動載入及儲存玩家的遊戲進度。這項服務也能讓玩家觸發使用者介面,更新或還原現有的儲存遊戲,或是建立新的儲存遊戲。
事前準備
建議您先複習已儲存的遊戲遊戲概念,這會對您很有幫助。
開始使用 Saved Games API 編寫程式碼之前:
資料格式和跨平台相容性
儲存至 Google 伺服器的遊戲進度存檔資料必須採用 std::vector<uint8_t> 格式。遊戲進度存檔服務會負責編碼資料,確保跨平台相容性;Android 應用程式可以將這項資料讀取為位元組陣列,不會有任何跨平台相容性問題。
為遊戲進度存檔資料選擇資料格式時,請避免使用平台專屬格式。強烈建議您使用 XML 或 JSON 等資料格式,這類格式在多個平台都有強大的程式庫支援。
啟用「遊戲進度存檔」服務
您必須先啟用存取權,才能使用遊戲進度存檔服務。如要這麼做,請使用 gpg::GameServices::Builder 建立服務時呼叫 EnableSnapshots()。這會在下次授權事件中,啟用「已儲存的遊戲」所需的額外授權範圍。
顯示遊戲進度存檔
您可以在遊戲中提供選項,讓玩家觸發儲存或還原遊戲進度存檔。玩家選取這個選項後,遊戲應會顯示現有的儲存空間,並允許玩家儲存至或載入其中一個空間,或建立新的遊戲進度存檔。請使用下列方法:
SnapshotManager::ShowSelectUIOperation(...)
遊戲進度存檔選項 UI 可讓玩家建立新的遊戲進度存檔、查看現有遊戲進度存檔,以及載入先前儲存的遊戲進度存檔。
SnapshotManager::SnapshotSelectUIResponse response;
if (IsSuccess(response.status)) {
if (response.data.Valid()) {
LogI("Description: %s", response.data.Description().c_str());
LogI("FileName %s", response.data.FileName().c_str());
//Opening the snapshot data
…
} else {
LogI("Creating new snapshot");
…
}
} else {
LogI("ShowSelectUIOperation returns an error %d", response.status);
}
以下範例說明如何顯示預設的遊戲進度存檔 UI,以及處理玩家的 UI 選項:
service_->Snapshots().ShowSelectUIOperation(
ALLOW_CREATE_SNAPSHOT,
ALLOW_DELETE_SNAPSHOT,
MAX_SNAPSHOTS,
SNAPSHOT_UI_TITLE,
[this](gpg::SnapshotManager::SnapshotSelectUIResponse const & response) {
…
}
如果以上述範例中的 ALLOW_CREATE_SNAPSHOT 大於使用者目前建立的實際快照數量,預設快照 UI 會為玩家提供建立新儲存遊戲的按鈕,而非選取現有遊戲。MAX_SNAPSHOTStrue(如果顯示按鈕,會位於使用者介面底部)。如果玩家點選這個按鈕,SnapshotSelectUIResponse 回應會有效,但沒有資料。
開啟及讀取遊戲進度存檔
如要存取遊戲進度存檔並讀取或修改內容,請先開啟代表該存檔的 SnapshotMetadata 物件。接著,呼叫 SnapshotManager::Read*() 方法。
以下範例說明如何開啟遊戲進度存檔:
LogI("Opening file");
service_->Snapshots()
.Open(current_snapshot_.FileName(),
gpg::SnapshotConflictPolicy::BASE_WINS,
[this](gpg::SnapshotManager::OpenResponse const & response) {
LogI("Reading file");
gpg::SnapshotManager::ReadResponse responseRead =
service_->Snapshots().ReadBlocking(response.data);
…
}
偵測並解決資料衝突
開啟 SnapshotMetadata 物件時,遊戲進度存檔服務會偵測是否有衝突的遊戲進度存檔。如果玩家在本機裝置中的遊戲進度存檔與 Google 伺服器中儲存的遠端版本不同步,就可能會發生資料衝突。
開啟遊戲進度存檔時指定的衝突政策,會告知遊戲進度存檔服務如何自動解決資料衝突。政策可以是下列其中一項:
| 衝突政策 | 說明 |
|---|---|
SnapshotConflictPolicy::MANUAL |
指出「已儲存的遊戲」服務不應執行任何解決動作。遊戲會改為執行自訂合併。 |
SnapshotConflictPolicy::LONGEST_PLAYTIME |
表示遊戲進度存檔服務應挑選遊戲時間值最大的遊戲進度存檔。 |
SnapshotConflictPolicy::BASE_WINS |
指出遊戲進度存檔服務應挑選基本遊戲進度存檔。 |
SnapshotConflictPolicy::REMOTE_WINS |
表示「遊戲進度存檔」服務應選擇遠端儲存的遊戲。遠端版本是指在其中一部玩家裝置上偵測到的已儲存遊戲版本,且時間戳記比基本版本新。 |
如果您指定的衝突政策不是 GPGSnapshotConflictPolicyManual,遊戲進度存檔服務會合併遊戲進度存檔,並透過產生的 SnapshotManager::OpenResponse 值傳回更新版本。遊戲可以開啟遊戲進度存檔、寫入資料,然後呼叫 SnapshotManager::Commit(...) 方法,將遊戲進度存檔提交至 Google 伺服器。
執行自訂合併
如果您將 SnapshotConflictPolicy::MANUAL 指定為衝突政策,遊戲必須先解決偵測到的任何資料衝突,才能對遊戲進度執行進一步的讀取或寫入作業。
在這種情況下,服務偵測到資料衝突時,會透過 SnapshotManager::OpenResponse 傳回下列參數:
conflict_id,用於專屬識別這項衝突 (您會在提交最終版本的遊戲進度時使用這個值);- 有衝突的遊戲進度基本版本;以及
- 發生衝突的遠端遊戲進度存檔版本。
遊戲必須決定要儲存哪些資料,然後呼叫 SnapshotManager::ResolveConflictBlocking() 方法,將最終版本提交/解決至 Google 伺服器。
//Resolve conflict
gpg::SnapshotManager::OpenResponse resolveResponse =
manager.ResolveConflictBlocking(openResponse.conflict_base, metadata_change,
openResponse.conflict_id);
寫入遊戲進度存檔
如要寫入遊戲進度,請先開啟代表該遊戲進度的 SnapshotMetadata 物件、解決偵測到的任何資料衝突,然後呼叫 SnapshotManager::Commit() 方法來提交遊戲進度變更。
以下範例說明如何建立變更並提交遊戲進度存檔。
首先,開啟要編輯的快照,並選擇基底解決所有衝突。
service_->Snapshots().Open( file_name, gpg::SnapshotConflictPolicy::BASE_WINS, [this](gpg::SnapshotManager::OpenResponse const &response) { if (IsSuccess(response.status)) { // metadata : gpg::SnapshotMetadata metadata = response.data; } else { // Handle snapshot open error here } });接著,建立遊戲進度存檔變更,其中包含用於封面圖片的圖片資料:
gpg::SnapshotMetadataChange::Builder builder; gpg::SnapshotMetadataChange metadata_change = builder.SetDescription("CollectAllTheStar savedata") .SetCoverImageFromPngData(pngData).Create();最後,提交遊戲進度存檔變更。
gpg::SnapshotManager::CommitResponse commitResponse = service_->Snapshots().CommitBlocking(metadata, metadata_change, SetupSnapshotData());資料參數包含您儲存的所有遊戲進度資料。 這項變更也包含其他遊戲進度存檔中繼資料,例如遊戲時間和遊戲進度存檔說明。
如果提交作業順利完成,玩家就能在遊戲進度存檔選擇 UI 中看到存檔。