Unity中借助Google Play Games插件保存多变量的方法咨询
Nice work getting the single float save up and running! Let’s build on that tutorial code to handle a full set of variables—this just requires wrapping your save data into a serializable object and adjusting how you serialize/deserialize it for GPG’s API. Here’s a step-by-step breakdown:
Step 1: Create a Serializable Save Data Class
First, define a class to hold all the variables you need to save. Mark it with [Serializable] so Unity can convert it to a storable format:
using System; using UnityEngine; [Serializable] public class GameSaveData { // Add all your saveable variables here—mix and match types as needed public float playerHealth; public float totalScore; public int currentLevel; public string playerUsername; public float[] resourceAmounts; // Example array of floats }
Step 2: Update the Save Method
Instead of saving a single float, we’ll serialize our GameSaveData object into a byte array (using Unity’s JsonUtility for simplicity) and store that in GPG:
public void SaveGame(GameSaveData saveData) { // Convert save data to a JSON string string jsonData = JsonUtility.ToJson(saveData); // Convert string to byte array for GPG storage byte[] byteData = System.Text.Encoding.UTF8.GetBytes(jsonData); // Use GPG's saved games API to commit the data PlayGamesPlatform.Instance.SavedGame.OpenWithAutomaticConflictResolution( "main_save_slot", // Your save slot name (can adjust this for multiple slots) DataSource.ReadCacheOrNetwork, ConflictResolutionStrategy.UseLongestPlaytime, (status, saveGame) => { if (status == SavedGameRequestStatus.Success) { saveGame.CommitUpdate(byteData, TimeSpan.FromMinutes(PlayGamesPlatform.Instance.GetPlaytime()), (updateStatus) => { if (updateStatus == SavedGameRequestStatus.Success) { Debug.Log("Save completed successfully!"); } else { Debug.LogError("Save failed: " + updateStatus); } }); } else { Debug.LogError("Failed to open save slot: " + status); } }); }
Step 3: Update the Load Method
When loading, we’ll pull the byte array from GPG, convert it back to JSON, then deserialize it into our GameSaveData object:
public void LoadGame(Action<GameSaveData> onLoadFinished) { PlayGamesPlatform.Instance.SavedGame.OpenWithAutomaticConflictResolution( "main_save_slot", DataSource.ReadCacheOrNetwork, ConflictResolutionStrategy.UseLongestPlaytime, (status, saveGame) => { if (status == SavedGameRequestStatus.Success) { saveGame.ReadBinaryData((readStatus, byteData) => { if (readStatus == SavedGameRequestStatus.Success) { // Convert byte array back to JSON string string jsonData = System.Text.Encoding.UTF8.GetString(byteData); // Deserialize into GameSaveData object GameSaveData loadedData = JsonUtility.FromJson<GameSaveData>(jsonData); onLoadFinished?.Invoke(loadedData); Debug.Log("Load completed successfully!"); } else { Debug.LogError("Failed to read save data: " + readStatus); onLoadFinished?.Invoke(null); } }); } else { Debug.LogError("Failed to open save slot: " + status); onLoadFinished?.Invoke(null); } }); }
Step 4: Use the Updated Methods
Now you can populate and save your data, then load it back to update your game state:
// Example: Saving your game state GameSaveData currentSave = new GameSaveData(); currentSave.playerHealth = 85.5f; currentSave.totalScore = 12500.0f; currentSave.currentLevel = 7; currentSave.resourceAmounts = new float[] { 10.0f, 3.5f, 0.0f }; SaveGame(currentSave); // Example: Loading the saved state LoadGame((loadedData) => { if (loadedData != null) { // Apply loaded values to your game Debug.Log("Loaded health: " + loadedData.playerHealth); Debug.Log("Loaded level: " + loadedData.currentLevel); } });
Important Notes
- Serializable Types: Stick to Unity-serializable variables (primitives, arrays, lists of serializable types,
Vector3, etc.). Avoid saving references toGameObjects or non-serializable objects—save data you can use to recreate the state instead. - Conflict Resolution: The tutorial uses
UseLongestPlaytime, but you can switch toUseMostRecentor another strategy if it fits your game better. - Async Operations: GPG save/load calls are asynchronous, so always use the callback methods to handle completion—don’t try to use loaded data immediately after calling
LoadGame.
内容的提问来源于stack exchange,提问作者Nicolas Decelle

