Unity 遊戲的遊戲進度存檔

本主題將說明針對 Unity 遊戲使用 Play 遊戲服務的遊戲進度存檔。

事前準備

顯示遊戲進度存檔 UI

呼叫以下內容,即可顯示標準 UI,用於選取或建立遊戲進度存檔項目:

    void ShowSelectUI() {
        uint maxNumToDisplay = 5;
        bool allowCreateNew = false;
        bool allowDelete = true;

        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.ShowSelectSavedGameUI("Select saved game",
            maxNumToDisplay,
            allowCreateNew,
            allowDelete,
            OnSavedGameSelected);
    }


    public void OnSavedGameSelected (SelectUIStatus status, ISavedGameMetadata game) {
        if (status == SelectUIStatus.SavedGameSelected) {
            // handle selected game save
        } else {
            // handle cancel or error
        }
    }

開啟遊戲進度存檔

若要讀取遊戲進度存檔,或在存檔中寫入資料,需要先開啟遊戲進度存檔。由於遊戲進度存檔狀態會在裝置本機製作快取,並將存檔狀態儲存到雲端上,因此儲存資料狀態可能會發生衝突。如果裝置嘗試把狀態儲存到雲端,但是其他裝置已經在目前位於雲端的資料中寫入資料,那麼就會發生衝突。開啟遊戲進度存檔資料時,就需要解決這類衝突。

能夠解決衝突的開放式方法有 2 種,第一種是 OpenWithAutomaticConflictResolution,這個方法可以接受標準解決方案策略類型,並自動解決衝突。另一種方法是 OpenWithManualConflictResolution,這個方法接受回呼方法,以便手動解決衝突。

如果想進一步瞭解這些方法,請參閱 GooglePlayGames/BasicApi/SavedGame/ISavedGameClient.cs

    void OpenSavedGame(string filename) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpened);
    }

    public void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            // handle reading or writing of saved game.
        } else {
            // handle error
        }
    }

寫入遊戲進度存檔

開啟遊戲進度存檔的檔案後,可以藉由在此檔案寫入資料儲存遊戲狀態。做法是呼叫 CommitUpdate。CommitUpdate 提供四種參數:

  1. 系統會向其中一種 Open 呼叫傳遞回呼,而需要傳遞給這個回呼的遊戲進度存檔中繼資料。
  2. 中繼資料的更新內容。
  3. 實際使用的資料位元組陣列
  4. 修訂完成後所呼叫的回呼。
    void SaveGame (ISavedGameMetadata game, byte[] savedData, TimeSpan totalPlaytime) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;

        SavedGameMetadataUpdate.Builder builder = new SavedGameMetadataUpdate.Builder();
        builder = builder
            .WithUpdatedPlayedTime(totalPlaytime)
            .WithUpdatedDescription("Saved game at " + DateTime.Now());
        if (savedImage != null) {
            // This assumes that savedImage is an instance of Texture2D
            // and that you have already called a function equivalent to
            // getScreenshot() to set savedImage
            // NOTE: see sample definition of getScreenshot() method below
            byte[] pngData = savedImage.EncodeToPNG();
            builder = builder.WithUpdatedPngCoverImage(pngData);
        }
        SavedGameMetadataUpdate updatedMetadata = builder.Build();
        savedGameClient.CommitUpdate(game, updatedMetadata, savedData, OnSavedGameWritten);
    }

    public void OnSavedGameWritten (SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            // handle reading or writing of saved game.
        } else {
            // handle error
        }
    }

    public Texture2D getScreenshot() {
        // Create a 2D texture that is 1024x700 pixels from which the PNG will be
        // extracted
        Texture2D screenShot = new Texture2D(1024, 700);

        // Takes the screenshot from top left hand corner of screen and maps to top
        // left hand corner of screenShot texture
        screenShot.ReadPixels(
            new Rect(0, 0, Screen.width, (Screen.width/1024)*700), 0, 0);
        return screenShot;
    }

讀取遊戲進度存檔

開啟遊戲進度存檔的檔案後,即可藉由讀取此檔案載入遊戲狀態。做法是呼叫 ReadBinaryData

    void LoadGameData (ISavedGameMetadata game) {
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.ReadBinaryData(game, OnSavedGameDataRead);
    }

    public void OnSavedGameDataRead (SavedGameRequestStatus status, byte[] data) {
        if (status == SavedGameRequestStatus.Success) {
            // handle processing the byte array data
        } else {
            // handle error
        }
    }

刪除遊戲進度存檔

開啟遊戲進度存檔的檔案後,即可刪除這個檔案。做法是呼叫 Delete

    void DeleteGameData (string filename) {
        // Open the file to get the metadata.
        ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
        savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,
            ConflictResolutionStrategy.UseLongestPlaytime, DeleteSavedGame);
    }

    public void DeleteSavedGame(SavedGameRequestStatus status, ISavedGameMetadata game) {
        if (status == SavedGameRequestStatus.Success) {
            ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;
            savedGameClient.Delete(game);
        } else {
            // handle error
        }
    }