Deozaan

PlayerSave.cs - An Alternative to Unity's PlayerPrefs

Mar 21st, 2012
1,014
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.14 KB | None | 0 0
  1. // PlayerSave by Sophie Houlden
  2. // http://twitter.com/S0phieH
  3. // http://wiki.unity3d.com/index.php?title=PlayerSave
  4.  
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.IO;
  8. using System;
  9. using System.Collections.Generic;
  10.  
  11. /*
  12.  * Class works almost exactly like playerprefs, but you can specify save locations by platform
  13.  *
  14.  * ~~~ features ~~~
  15.  * - option to fall back to player prefs (this is a must for some platforms)
  16.  * - all functions of PlayerPrefs exist here, use the scripts the same way
  17.  *
  18.  * ~~~ Imperfections ~~~
  19.  * - to be able to save when the game closes (like playerprefs does), the script needs
  20.  *     to instantiate a GameObject called "_SaveCaller"
  21.  * - no scrambling/obfusimacation of the save data right now, so users can easily hack it
  22.  * - as with player prefs, there's no built in way to have separate save 'slots' for the
  23.  *     same game and save directory, add this yourself if you want it :)
  24.  * - you might not like the way I load/save from the file, I'm no expert so
  25.  *     if you can do better feel free :)
  26.  *
  27.  *
  28.  * ~~~ Instructions ~~~
  29.  * you must go through the Prepare() function, and set all relevant stuff, for all platforms
  30.  * that you want to target.
  31.  * don't forget to change the 'gameName' variable if your path uses it, or
  32.  * you could overwrite other game's saves :P
  33.  *
  34.  * ~~~ Licence ~~~
  35.  * Licence for this is whatever I guess, do what you like with it,
  36.  * I don't care about credit either. full free use :)
  37.  *
  38.  * */
  39.  
  40. public class SaveCaller : MonoBehaviour {
  41.     void Start() {
  42.         DontDestroyOnLoad(gameObject);
  43.     }
  44.     void OnApplicationQuit() {
  45.         PlayerSave.EndNow();
  46.     }
  47. }
  48.  
  49. static public class PlayerSave {
  50.  
  51.     //loads all data, happens first time you set or get, but can be called earlier to avoid a jump
  52.     static public void Prepare() {
  53.         if (dataLoaded)
  54.             return;
  55.         dataLoaded = true;
  56.  
  57.         //default path
  58.         savePath = Application.persistentDataPath;
  59.         saveFile = "Save.sav";
  60.         gameName = "Change this";
  61.  
  62.         //don't fallback by default
  63.         fallback = false;
  64.  
  65.         //platform dependent settings:
  66.         #if UNITY_STANDALONE_OSX
  67.         fallback = false;
  68.         #endif
  69.  
  70.         #if UNITY_STANDALONE_WIN
  71.         //saves to where some rockpapershotgun folk want the pc save standard to be: http://www.rockpapershotgun.com/2012/01/24/start-it-the-place-to-put-save-games
  72.         fallback = false;
  73.         savePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\My Games\\" + gameName + "\\Saves";
  74.         #endif
  75.  
  76.         #if UNITY_DASHBOARD_WIDGET
  77.         fallback = true;
  78.         #endif
  79.  
  80.         #if UNITY_WEBPLAYER
  81.         fallback = true;
  82.         #endif
  83.  
  84.         #if UNITY_WII
  85.         fallback = true;
  86.         #endif
  87.        
  88.         #if UNITY_IPHONE
  89.         fallback = true;
  90.         #endif
  91.  
  92.         #if UNITY_ANDROID
  93.         fallback = true;
  94.         #endif
  95.  
  96.         #if UNITY_PS3
  97.         fallback = true;
  98.         #endif
  99.  
  100.         #if UNITY_XBOX360
  101.         fallback = true;
  102.         #endif
  103.        
  104.         #if UNITY_FLASH
  105.         fallback = true;
  106.         #endif
  107.  
  108.         //if we aren't going to use playerprefs, let's load the data
  109.         if (!fallback) {
  110.             //load from file here
  111.  
  112.             LoadSavedData();
  113.  
  114.             //create empty gameobject that calls EndNow when the application quits
  115.             GameObject saveCaller = new GameObject();
  116.             saveCaller.AddComponent<SaveCaller>();
  117.             saveCaller.name = "_SaveCaller";
  118.         }
  119.     }
  120.  
  121.     static public void SetInt(string key, int val) {
  122.         Prepare();
  123.  
  124.         //playerprefs fallback
  125.         if (fallback) {
  126.             PlayerPrefs.SetInt(key, val);
  127.             return;
  128.         }
  129.  
  130.         //set the int if it already exists
  131.         for (int i = 0; i < intKeys.Count; i++) {
  132.             if (intKeys[i] == key) {
  133.                 ints[i] = val;
  134.                 return;
  135.             }
  136.         }
  137.  
  138.         //int does not exist, we create it
  139.         ints.Add(val);
  140.         intKeys.Add(key);
  141.     }
  142.  
  143.     static public int GetInt(string key, int defaultVal) {
  144.         Prepare();
  145.  
  146.         //playerprefs fallback
  147.         if (fallback) {
  148.             return PlayerPrefs.GetInt(key, defaultVal);
  149.         }
  150.  
  151.         //return int if it exists
  152.         for (int i = 0; i < intKeys.Count; i++) if (intKeys[i] == key)
  153.                 return ints[i];
  154.  
  155.         //otherwise return default value
  156.         return defaultVal;
  157.     }
  158.  
  159.     static public void SetFloat(string key, float val) {
  160.         Prepare();
  161.  
  162.         //playerprefs fallback
  163.         if (fallback) {
  164.             PlayerPrefs.SetFloat(key, val);
  165.             return;
  166.         }
  167.  
  168.         //set the float if it already exists
  169.         for (int i = 0; i < floatKeys.Count; i++) {
  170.             if (floatKeys[i] == key) {
  171.                 floats[i] = val;
  172.                 return;
  173.             }
  174.         }
  175.  
  176.         //float does not exist, we create it
  177.         floats.Add(val);
  178.         floatKeys.Add(key);
  179.     }
  180.  
  181.     static public float GetFloat(string key, float defaultVal) {
  182.         Prepare();
  183.  
  184.         //playerprefs fallback
  185.         if (fallback) {
  186.             return PlayerPrefs.GetFloat(key, defaultVal);
  187.         }
  188.  
  189.         //return float if it exists
  190.         for (int i = 0; i < floatKeys.Count; i++) if (floatKeys[i] == key)
  191.                 return floats[i];
  192.  
  193.         //otherwise return default value
  194.         return defaultVal;
  195.     }
  196.  
  197.     static public void SetString(string key, string val) {
  198.         Prepare();
  199.  
  200.         //playerprefs fallback
  201.         if (fallback) {
  202.             PlayerPrefs.SetString(key, val);
  203.             return;
  204.         }
  205.  
  206.         //set the string if it already exists
  207.         for (int i = 0; i < stringKeys.Count; i++) {
  208.             if (stringKeys[i] == key) {
  209.                 strings[i] = val;
  210.                 return;
  211.             }
  212.         }
  213.  
  214.         //string does not exist, we create it
  215.         strings.Add(val);
  216.         stringKeys.Add(key);
  217.     }
  218.  
  219.     static public string GetString(string key, string defaultVal) {
  220.         Prepare();
  221.  
  222.         //playerprefs fallback
  223.         if (fallback) {
  224.             return PlayerPrefs.GetString(key, defaultVal);
  225.         }
  226.  
  227.         //return string if it exists
  228.         for (int i = 0; i < stringKeys.Count; i++) if (stringKeys[i] == key)
  229.                 return strings[i];
  230.  
  231.         //otherwise return default value
  232.         return defaultVal;
  233.     }
  234.  
  235.     static public bool HasKey(string key) {
  236.         Prepare();
  237.  
  238.         //playerprefs fallback
  239.         if (fallback) {
  240.             return PlayerPrefs.HasKey(key);
  241.         }
  242.  
  243.         for (int i = 0; i < intKeys.Count; i++) if (intKeys[i] == key)
  244.                 return true;
  245.         for (int i = 0; i < floatKeys.Count; i++) if (floatKeys[i] == key)
  246.                 return true;
  247.         for (int i = 0; i < stringKeys.Count; i++) if (stringKeys[i] == key)
  248.                 return true;
  249.  
  250.         return false;
  251.     }
  252.  
  253.     static public void DeleteKey(string key) {
  254.         Prepare();
  255.  
  256.         //playerprefs fallback
  257.         if (fallback) {
  258.             PlayerPrefs.DeleteKey(key);
  259.             return;
  260.         }
  261.  
  262.     }
  263.  
  264.     static public void DeleteAll() {
  265.         Prepare();
  266.  
  267.         //playerprefs fallback
  268.         if (fallback) {
  269.             PlayerPrefs.DeleteAll();
  270.             return;
  271.         }
  272.     }
  273.  
  274.     static public void Save() {
  275.         //playerprefs fallback
  276.         if (fallback) {
  277.             PlayerPrefs.Save();
  278.             return;
  279.         }
  280.  
  281.         //only need to save if something has changed
  282.         if (!dataLoaded)
  283.             return;
  284.  
  285.         //save now
  286.         string outputString = "I\n";
  287.         for (int i = 0; i < ints.Count; i++) {
  288.             outputString += intKeys[i] + "," + ints[i].ToString() + "\n";
  289.         }
  290.  
  291.         outputString += "F\n";
  292.         for (int i = 0; i < floats.Count; i++) {
  293.             outputString += floatKeys[i] + "," + floats[i].ToString() + "\n";
  294.         }
  295.  
  296.         outputString += "S\n";
  297.         for (int i = 0; i < strings.Count; i++) {
  298.             outputString += stringKeys[i] + "," + strings[i] + "\n";
  299.         }
  300.  
  301.         if (!File.Exists(savePath)) {
  302.             Directory.CreateDirectory(savePath);
  303.         }
  304.  
  305.         File.WriteAllText(savePath + "\\" + saveFile, outputString);
  306.     }
  307.  
  308.     //data and keys
  309.     static List<int> ints = new List<int>();
  310.     static List<string> intKeys = new List<string>();
  311.     static List<float> floats = new List<float>();
  312.     static List<string> floatKeys = new List<string>();
  313.     static List<string> strings = new List<string>();
  314.     static List<string> stringKeys = new List<string>();
  315.  
  316.     //have we loaded the data yet?
  317.     static bool dataLoaded = false;
  318.  
  319.     static bool fallback;
  320.     static string savePath;
  321.     static string saveFile;
  322.     static string gameName;
  323.  
  324.     static void LoadSavedData() {
  325.  
  326.         if (!File.Exists(savePath + "\\" + saveFile))
  327.             return;
  328.  
  329.         string[] loadedFile = File.ReadAllLines(savePath + "\\" + saveFile);
  330.  
  331.         string loadState = "";
  332.         //bool gotKey = false; // This value is never used, so it's safe to leave commented out.
  333.  
  334.         for (int i = 0; i < loadedFile.Length; i++) {
  335.             if (loadedFile[i] == "I") {
  336.                 //start loading the ints
  337.                 loadState = "ints";
  338.             } else if (loadedFile[i] == "F") {
  339.                 //start loading the floats
  340.                 loadState = "floats";
  341.             } else if (loadedFile[i] == "S") {
  342.                 //start loading the strings
  343.                 loadState = "strings";
  344.             } else {
  345.                 //load a key
  346.                 int endKeyIndex = -1;
  347.                 for (int k = loadedFile[i].Length - 1; k >= 0; k--) {
  348.                     if (loadedFile[i].Substring(k, 1) == "," && endKeyIndex == -1) {
  349.                         endKeyIndex = k;
  350.                     }
  351.                 }
  352.  
  353.                 string loadKey = loadedFile[i].Substring(0, endKeyIndex);
  354.                 string loadVar = loadedFile[i].Substring(endKeyIndex + 1, loadedFile[i].Length - endKeyIndex - 1);
  355.  
  356.                 if (loadState == "ints") {
  357.                     intKeys.Add(loadKey);
  358.                     ints.Add(MakeInt(loadVar));
  359.                 } else if (loadState == "floats") {
  360.                     floatKeys.Add(loadKey);
  361.                     floats.Add(MakeFloat(loadVar));
  362.                 } else if (loadState == "strings") {
  363.                     stringKeys.Add(loadKey);
  364.                     strings.Add(loadVar);
  365.                 }
  366.             }
  367.         }
  368.     }
  369.  
  370.     static float MakeFloat(string v) {
  371.         return System.Convert.ToSingle(v.Trim(), new System.Globalization.CultureInfo("en-US"));
  372.     }
  373.  
  374.     static int MakeInt(string v) {
  375.         return System.Convert.ToInt32(v.Trim(), new System.Globalization.CultureInfo("en-US"));
  376.     }
  377.  
  378.     static public void EndNow() {
  379.         Save();
  380.     }
  381. }
Advertisement
Add Comment
Please, Sign In to add comment