• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by furic · Apr 08, 2016 at 07:12 AM · playerprefssavegoogle play gamesprogresssnapshot

Migranting PlayerPrefs local saves to Google Play Games Saved Game (Snapshots)

Currently my game save all progress in local using PlayerPrefs, we are moving forward trying to implement Google Play Games Saved Games (Snapshots) and integrating the all players' save to there.

Since PlayerPrefs use key-value pairs but Snapshots just use plain bytes, I would like to know if there's already a script or plugin for it to save my time? Or I will need to do data serialization from the PlayerPrefs on my own, just like taught in here?

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image furic · Apr 11, 2016 at 05:27 AM 0
Share

no one can answer?

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by furic · Apr 27, 2016 at 08:06 AM

For those who look for the answer, here's my code integrating using persistence save/load with Play Games. Basically I have a GameSave Class and save it to a binary file in local, merge is if there's a Play Games snapshots. And use GameSaveManager.GetInt instead of PlayerPrefs.GetInt, etc.

GameSaveManager.cs:

 using UnityEngine;
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
 using System.Runtime.Serialization.Formatters.Binary;
 using Prime31;
 
 public class GameSaveManager : MonoBehaviour
 {
 
     // Some faking filename
     private const string FILENAME_GAMESAVE = "Physics.dat";
 
     // Events fired when progress is synced from iCloud / Play Games
     public static event Action loadOnlineCompletedEvent;
 
     private static GameSaveManager _instance;
 
     public static GameSaveManager instance {
         get {
             if (_instance == null) {
                 GameObject g = new GameObject ("GameSaveManager");
                 _instance = g.AddComponent<GameSaveManager> ();
                 DontDestroyOnLoad (g);
             }
             return _instance;
         }
     }
 
     [SerializeField] private bool _debugMode = false;
 
     private static string gameSaveFilePath {
         get {
             return Path.Combine (Application.persistentDataPath, FILENAME_GAMESAVE);
         }
     }
 
     void Awake ()
     {
         _instance = this; // For debug only
 
         #if UNITY_ANDROID
         GPGManager.authenticationSucceededEvent += OnAuthenticationSucceeded;
         GPGManager.loadSnapshotSucceededEvent += OnLoadSnapshotSucceeded;
         GPGManager.saveSnapshotSucceededEvent += OnSaveSnapshotSucceeded;
         GPGManager.saveSnapshotFailedEvent += OnSaveSnapshotFailed;
         #endif
     }
 
     #region Get/Set
 
     public static bool GetBool (string key, bool defaultValue = false)
     {
         try {
             return (bool)(typeof(GameSave)).GetField (key).GetValue (GameSave.instance);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:GetBool - Cannot find key={ 0}, error={ 1}", key, e));
             return defaultValue;
         }
     }
 
     public static void SetBool (string key, bool value, bool syncOnline = true)
     {
         try {
             (typeof(GameSave)).GetField (key).SetValue (GameSave.instance, value);
             if (syncOnline)
                 SaveOnline ();
         }  catch (System.Exception e) {
             Debug.Log (string.Format ("GameSaveManager:SetBool - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     public static int GetInt (string key, int defaultValue = 0)
     {
         try {
             return (int)(typeof(GameSave)).GetField (key).GetValue (GameSave.instance);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:GetInt - Cannot find key={ 0}, error={ 1}", key, e));
             return defaultValue;
         }
     }
 
     public static void SetInt (string key, int value, bool syncOnline = true)
     {
         try {
             (typeof(GameSave)).GetField (key).SetValue (GameSave.instance, value);
             if (syncOnline)
                 SaveOnline ();
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:SetInt - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     public static string GetString (string key, string defaultValue = "")
     {
         try {
             return (string)(typeof(GameSave)).GetField (key).GetValue (GameSave.instance);
         }  catch (System.Exception e) {
             Debug.Log (string.Format ("GameSaveManager:SetString - Cannot find key={ 0}", key));
             return defaultValue;
         }
     }
 
     public static void SetString (string key, string value, bool syncOnline = true)
     {
         try {
             (typeof(GameSave)).GetField (key).SetValue (GameSave.instance, value);
             if (syncOnline)
                 SaveOnline ();
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:SetString - Cannot find key={ 0}", key));
         }
     }
 
     public static DateTime GetDateTime (string key, DateTime defaultValue = default (DateTime))
     {
         try {
             return (DateTime)(typeof(GameSave)).GetField (key).GetValue (GameSave.instance);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:GetDateTime - Cannot find key={ 0}, error={ 1}", key, e));
             return defaultValue;
         }
     }
 
     public static void SetDateTime (string key, DateTime value, bool syncOnline = true)
     {
         try {
             (typeof(GameSave)).GetField (key).SetValue (GameSave.instance, value);
             if (syncOnline)
                 SaveOnline ();
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:SetDateTime - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     public static List<int> GetIntList (string key, List<int> defaultValue = null)
     {
         try {
             return (List<int>)(typeof(GameSave)).GetField (key).GetValue (GameSave.instance);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:GetIntList - Cannot find key={ 0}, error={ 1}", key, e));
             return defaultValue != null ? defaultValue : new List<int> ();
         }
     }
 
     public static void SetIntList (string key, List<int> value, bool syncOnline = true)
     {
         try {
             (typeof(GameSave)).GetField (key).SetValue (GameSave.instance, value);
             if (syncOnline)
                 SaveOnline ();
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:SetIntList - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     public static void AddIntList (string key, int value, bool syncOnline = true)
     {
         try {
             List<int> tmp = GetIntList (key);
             tmp.Add (value);
             SetIntList (key, tmp, syncOnline);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:AddIntList - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     public static void RemoveIntList (string key, int value, bool syncOnline = true)
     {
         try {
             List<int> tmp = GetIntList (key);
             tmp.Remove (value);
             SetIntList (key, tmp, syncOnline);
         }  catch (System.Exception e) {
             Debug.LogWarning (string.Format ("GameSaveManager:RemoveIntList - Cannot find key={ 0}, error={ 1}", key, e));
         }
     }
 
     #endregion
 
     #region Local Save / Load
 
     public static void Load ()
     {    
         if (File.Exists (gameSaveFilePath)) {
 
             GameSave.instance = GameSave.FromBytes (P31CloudFile.readAllBytes (FILENAME_GAMESAVE));
 
             //             Debug.Log ("SavedGameManager:Load - Loading " + savedGameFilePath);
 
             BinaryFormatter bf = new BinaryFormatter ();
             FileStream fs = File.Open (gameSaveFilePath, FileMode.Open);
 
             GameSave.instance = (GameSave)bf.Deserialize (fs);
             fs.Close ();
 
             //            Debug.Log ("SavedGameManager:Load - GameSave=" + GameSave.instance);
 
             #endif
 
         }  else { // Create an empty one
             GameSave.instance = new GameSave ();
         }
     }
 
     public static void Save ()
     {
         if (instance._debugMode)
             Debug.Log ("SavedGameManager:Save - Saving " + gameSaveFilePath);
 
         BinaryFormatter bf = new BinaryFormatter ();
         FileStream fs = File.Create (gameSaveFilePath);
 
         bf.Serialize (fs, GameSave.instance);
         fs.Close ();
     }
 
     #endregion
 
     #region Play Games Snapshots Save / Load
 
     #if UNITY_ANDROID
     private void OnAuthenticationSucceeded (string param)
     {
     PlayGameServices.loadSnapshot ("GameSave");
     }
 
     private void OnLoadSnapshotSucceeded (GPGSnapshot snapshot)
     {
     if (instance._debugMode) {
     Debug.Log ("GameSaveManager:OnLoadSnapshotSucceeded()");
     Prime31.Utils.logObject (snapshot);
     }
 
     GameSave.instance.Merge (snapshot.snapshotData);
 
     if (loadOnlineCompletedEvent != null)
     loadOnlineCompletedEvent ();
     }
 
     private static void DoSaveOnline ()
     {
     PlayGameServices.saveSnapshot ("GameSave", true, GameSave.instance.ToBytes (), StringHelper.Localize ("Game save on {0}", DateTime.Now.ToString ("yyMMdd-HHmmss")));
     }
 
     private void OnSaveSnapshotSucceeded ()
     {
     Debug.Log( "OnSaveSnapshotSucceeded" );
     }
 
 
     private void OnSaveSnapshotFailed (string error)
     {
     Debug.Log( "OnSaveSnapshotFailed: " + error );
     }
     #endif
 
     #endregion
 
     #region Save Online
 
     private static float lastSaveOnlineTime = -10;
     // To prevent multiple sync in short period
     private static IEnumerator waitAndSaveOnlineCoroutine;
 
     private IEnumerator WaitAndSaveOnlineCoroutine ()
     {
         yield return new WaitForSeconds (5);
         SaveOnline ();
     }
 
     public static void SaveOnline ()
     {
         if (!PlayGameServices.isSignedIn ())
         return;
 
         if (instance._debugMode)
             Debug.Log (string.Format ("GameSaveManager:SaveOnline - GameSave.instance={ 0}, bytes.Length={ 1}", GameSave.instance, GameSave.instance.ToBytes ().Length));
 
         if (waitAndSaveOnlineCoroutine != null) // If already schedule, cancel it
             instance.StopCoroutine (waitAndSaveOnlineCoroutine);
 
         if (Time.unscaledTime - lastSaveOnlineTime < 5) { // Have a sync within 5 seconds, schedule it and return
             waitAndSaveOnlineCoroutine = instance.WaitAndSaveOnlineCoroutine ();
             instance.StartCoroutine (waitAndSaveOnlineCoroutine);
         }  else {
             DoSaveOnline ();
             lastSaveOnlineTime = Time.unscaledTime;
         }
     }
 
     #endregion
 
     void OnApplicationPause (bool isPaused)
     {
         if (isPaused) // Save on pausing / quiting the game
             Save ();
     }
 
 }


GameSave.cs

 using UnityEngine;
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Text;
 
 [Serializable]
 public class GameSave
 {
 
     public int coins; // Used in MoneyManager
     public int freeCoinsCount; // Used in EventManager
     public DateTime freeCoinsDateTime;
     public bool removedAd; // Userd in AdsManager
     public string rewardedUpgradeVersion; // Used in RewardManager
     public int rewardedSurvivalSeconds;
     public List<int> ownedShips = new List<int> (); // Used in FlyerItem
     public List<int> ownedExpansions = new List<int> (); // Used in WorldInfo
 
     // How to merge a newer save from server
     public void Merge (GameSave gs)
     {
         if (gs == null) // Return if invalid data
             return;
 
         Debug.Log ("GameSave:Merge - merging " + gs);
 
         coins = gs.coins; // Get the newest
         freeCoinsCount = Mathf.Max (freeCoinsCount, gs.freeCoinsCount); // Get largest
         freeCoinsDateTime = gs.freeCoinsDateTime; // Get the newest
         removedAd = removedAd || gs.removedAd; // True if either one is true
         rewardedUpgradeVersion = gs.rewardedUpgradeVersion;
         rewardedSurvivalSeconds = Mathf.Max (rewardedSurvivalSeconds, gs.rewardedSurvivalSeconds); // Get largest
         ownedShips.AddRange (gs.ownedShips); // Merge 2 lists
         ownedShips.Distinct ().ToList ();
         ownedExpansions.AddRange (gs.ownedExpansions); // Merge 2 lists
         ownedExpansions.Distinct ().ToList ();
     }
 
     #region Consistent code - Don't change below
 
     private static GameSave _instance;
 
     public static GameSave instance {
         get {
             if (_instance == null)
                 GameSaveManager.Load ();
             return _instance;
         }
         set {
             _instance = value;
         }
     }
 
     // For debug
     public override string ToString ()
     {
         StringBuilder sb = new StringBuilder ();
         sb.Append ("[GameSave: ");
         foreach (System.Reflection.FieldInfo fi in this.GetType().GetFields (BindingFlags.Instance | BindingFlags.Public)) {
             sb.Append (fi.Name);
             sb.Append ("=");
             if (typeof (IList).IsAssignableFrom (fi.FieldType)) { // A list
                 sb.Append (StringHelper.ListToString (fi.GetValue (this) as IList));
             } else
                 sb.Append (fi.GetValue (this));
             sb.Append (", ");
         }
         sb.Length -= 2; // Remove the last ', '
         sb.Append ("]");
         return sb.ToString();
     }
 
     public void Merge (byte[] bytes)
     {
         Merge (GameSave.FromBytes (bytes));
     }
 
     public static GameSave FromBytes (byte[] bytes)
     {
         if (bytes == null || bytes.Length == 0) {
             Debug.LogWarning ("SavedGameData:FromBytes - Serialization of zero sized array");
             return null;
         }
 
         using (MemoryStream ms = new MemoryStream (bytes)) {
             try {
                 BinaryFormatter formatter = new BinaryFormatter ();
                 GameSave data = (GameSave)formatter.Deserialize (ms);
                 return data;
             } catch (Exception e) {
                 Debug.LogError ("SavedGameData:FromBytes - Error when reading stream: " + e.Message);
             }
         }
         return null;
     }
 
     public byte[] ToBytes ()
     {
         BinaryFormatter bf = new BinaryFormatter ();
         using (MemoryStream ms = new MemoryStream ()) {
             bf.Serialize (ms, this);
             return ms.ToArray ();
         }
     }
 
     #endregion
 
 }


Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image GreenCubeGames · Sep 15, 2017 at 09:46 PM 0
Share

using Prime31; don't work here

avatar image
-1

Answer by SaVe1418 · May 09, 2017 at 05:21 AM

Thank you for the post furic. I am using visual scripting for my game and I have a lot of variables stored in the PlayerPrefs (like gold,combatants,gems, loot etc.), how can I do it with your code? They are all stored in string data = PlayerPrefs.GetString("savegameAUTO"); I am a newbie in programming. Is there any way to integrate this?

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image SweatyChair · May 09, 2017 at 11:25 AM 0
Share

GameSave$$anonymous$$anager.GetString("savegameAUTO");

then you need to put string savegameAUTO in GameSave.cs;

avatar image SaVe1418 SweatyChair · May 09, 2017 at 09:31 PM 0
Share

Thanks a lot SweatyChair, I will give it a shot.

avatar image SaVe1418 SweatyChair · May 10, 2017 at 02:02 PM 0
Share

@SweatyChair , where exactly should I put the GameSave$$anonymous$$anager.GetString("savegameAUTO"); ?

avatar image pooja_pandey · Mar 08, 2019 at 10:05 AM 0
Share

@furic - Can you please share the P31CloudFile?

avatar image
0

Answer by Giampy_Normo · Jun 27, 2021 at 06:01 PM

hi there, i'm trying that script and visual studio give me error when put "using prime31;" hat can be the problem? im new at all of this

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

50 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Playerprefs Question 0 Answers

Checkpoint with PlayerPrefs 0 Answers

How to save progress in the game? 1 Answer

How to constantly save game progress? 1 Answer

How to save gameobject values with respect to scene? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges