From 84cebac487cb7810133c3953e12bd35c33683233 Mon Sep 17 00:00:00 2001 From: chrisgregan Date: Sat, 28 Jun 2014 23:57:59 +0100 Subject: [PATCH] Improved save game system. - Went back to having to explicitly load / save game variables --- Assets/Fungus/Scripts/Game.cs | 26 +--- Assets/Fungus/Scripts/GameController.cs | 17 +-- Assets/Fungus/Scripts/Variables.cs | 187 +++++++++++++++++------- 3 files changed, 144 insertions(+), 86 deletions(-) diff --git a/Assets/Fungus/Scripts/Game.cs b/Assets/Fungus/Scripts/Game.cs index b9891484..b058ae3e 100644 --- a/Assets/Fungus/Scripts/Game.cs +++ b/Assets/Fungus/Scripts/Game.cs @@ -31,13 +31,6 @@ namespace Fungus */ public bool showLinks = true; - /** - * Deletes all previously stored variables on launch. - * Disable this if you want to have game variables persist between game launches. - * It is then up to you to provide an in-game option to reset game variables. - */ - public bool deleteVariables = true; - /** * Time for fade transition to complete when moving to a different Room. */ @@ -123,11 +116,6 @@ namespace Fungus commandQueue.AddCommand(new Command.MoveToRoom(activeRoom)); commandQueue.Execute(); } - - if (deleteVariables) - { - Variables.DeleteAll(); - } } public virtual void Update() @@ -186,24 +174,24 @@ namespace Fungus } /** - * Save the current game variables to persistant storage. - * Store the currently loaded scene name so that Game.LoadGame() can automatically move to the appropriate scene. + * Save the current game variables to persistant storage using a save game name. + * Stores the currently loaded scene name so that Game.LoadGame() can automatically move to the appropriate scene. */ - public void SaveGame() + public void SaveGame(string saveName = "_fungus") { - SetString("_scene", Application.loadedLevelName); - Variables.Save(); + Variables.SetString("_scene", Application.loadedLevelName); + Variables.Save(saveName); } /** - * Loads the current game state from persistant storage. + * Loads the current game state from persistant storage using a save game name. * This will cause the scene specified in the "_scene" string to be loaded. * Each scene in your game should contain the necessary code to restore the current game state based on saved data. * @param saveName The name of the saved game data. */ public void LoadGame(string saveName = "_fungus") { - Variables.SetSaveName(saveName); + Variables.Load(saveName); string sceneName = Variables.GetString("_scene"); if (sceneName.Length > 0) { diff --git a/Assets/Fungus/Scripts/GameController.cs b/Assets/Fungus/Scripts/GameController.cs index dc239b13..6729bcda 100644 --- a/Assets/Fungus/Scripts/GameController.cs +++ b/Assets/Fungus/Scripts/GameController.cs @@ -88,20 +88,11 @@ namespace Fungus * Save the current game state to persistant storage. * @param saveName The name of the saved game data. */ - [Obsolete("Use Save() instead and use Variables.SetSaveName() if you need to set the save name.")] - public static void Save(string saveName) - { - GameController.Save(); - } - - /** - * Saves the current game variables to persistant storage. - */ - public static void Save() + public static void Save(string saveName = "_fungus") { CommandQueue commandQueue = Game.GetInstance().commandQueue; commandQueue.AddCommand(new Command.Call(delegate { - Game.GetInstance().SaveGame(); + Game.GetInstance().SaveGame(saveName); })); } @@ -371,7 +362,9 @@ namespace Fungus [Obsolete("Use Variables.DeleteKey() instead")] public static void ClearValue(string key) { - Variables.DeleteKey(key); + Variables.SetInteger(key, 0); + Variables.SetFloat(key, 0); + Variables.SetBoolean(key, false); } /** diff --git a/Assets/Fungus/Scripts/Variables.cs b/Assets/Fungus/Scripts/Variables.cs index 07281559..466f64ad 100644 --- a/Assets/Fungus/Scripts/Variables.cs +++ b/Assets/Fungus/Scripts/Variables.cs @@ -1,128 +1,215 @@ using UnityEngine; +using System; using System.Collections; +using System.Collections.Generic; using System.Text.RegularExpressions; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; namespace Fungus { /** - * Peristent data storage class for tracking game state. - * Provides a basic save game system. + * Static data storage class for managing global game variables. + * Provides save and load functionality for persistent storage between game sessions. */ public class Variables { - static string saveName = "_fungus"; + static Dictionary stringDict = new Dictionary(); + static Dictionary intDict = new Dictionary(); + static Dictionary floatDict = new Dictionary(); + static Dictionary boolDict = new Dictionary(); /** - * Sets a name to prefix before all keys used with Set & Get methods. - * You can use this to support multiple save data profiles, (e.g. for multiple users or a list of checkpoints). + * Save the variable dictionaries to persistent storage using a name tag. */ - static public void SetSaveName(string _saveName) + public static void Save(string saveName) { - saveName = _saveName; - } + // Save strings + { + var b = new BinaryFormatter(); + var m = new MemoryStream(); + b.Serialize(m, stringDict); + PlayerPrefs.SetString(saveName + "." + "stringDict", Convert.ToBase64String(m.GetBuffer())); + } - /** - * Save the variables state to persistent storage. - */ - static public void Save() - { + // Save ints + { + var b = new BinaryFormatter(); + var m = new MemoryStream(); + b.Serialize(m, intDict); + PlayerPrefs.SetString(saveName + "." + "intDict", Convert.ToBase64String(m.GetBuffer())); + } + + // Save floats + { + var b = new BinaryFormatter(); + var m = new MemoryStream(); + b.Serialize(m, floatDict); + PlayerPrefs.SetString(saveName + "." + "floatDict", Convert.ToBase64String(m.GetBuffer())); + } + + // Save bools + { + var b = new BinaryFormatter(); + var m = new MemoryStream(); + b.Serialize(m, boolDict); + PlayerPrefs.SetString(saveName + "." + "boolDict", Convert.ToBase64String(m.GetBuffer())); + } PlayerPrefs.Save(); } /** - * Deletes all stored variables. + * Loads the variable dictionaries from persistent storage using a name tag. */ - static public void DeleteAll() + public static void Load(string saveName) { - PlayerPrefs.DeleteAll(); + var stringData = PlayerPrefs.GetString(saveName + "." + "stringDict"); + if (string.IsNullOrEmpty(stringData)) + { + stringDict.Clear(); + } + else + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(stringData)); + stringDict = (Dictionary)b.Deserialize(m); + } + + var floatData = PlayerPrefs.GetString(saveName + "." + "floatDict"); + if (!string.IsNullOrEmpty(floatData)) + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(floatData)); + floatDict = b.Deserialize(m) as Dictionary; + } + + var intData = PlayerPrefs.GetString(saveName + "." + "intDict"); + if (!string.IsNullOrEmpty(intData)) + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(intData)); + intDict = b.Deserialize(m) as Dictionary; + } + + var boolData = PlayerPrefs.GetString(saveName + "." + "boolDict"); + if (!string.IsNullOrEmpty(boolData)) + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(boolData)); + boolDict = b.Deserialize(m) as Dictionary; + } } /** - * Deletes a single stored variable. + * Clears all stored variables. */ - static public void DeleteKey(string key) + public static void ClearAll() { - PlayerPrefs.DeleteKey(AddPrefix(key)); + stringDict.Clear(); + intDict.Clear(); + floatDict.Clear(); + boolDict.Clear(); } /** * Returns the float variable associated with the key. */ - static public float GetFloat(string key) + public static float GetFloat(string key) { - return PlayerPrefs.GetFloat(AddPrefix(key)); + if (String.IsNullOrEmpty(key) || + !floatDict.ContainsKey(key)) + { + return 0; + } + + return floatDict[key]; } /** * Returns the integer variable associated with the key. */ - static public int GetInteger(string key) + public static int GetInteger(string key) { - return PlayerPrefs.GetInt(AddPrefix(key)); + if (intDict == null) + { + Debug.Log ("Dict is null somehow"); + } + + if (String.IsNullOrEmpty(key) || + !intDict.ContainsKey(key)) + { + return 0; + } + + return intDict[key]; } /** * Returns the boolean variable associated with the key. */ - static public bool GetBoolean(string key) + public static bool GetBoolean(string key) { - return (bool)(PlayerPrefs.GetInt(AddPrefix(key)) != 0); + if (String.IsNullOrEmpty(key) || + !boolDict.ContainsKey(key)) + { + return false; + } + + return boolDict[key]; } /** * Returns the string variable associated with the key. */ - static public string GetString(string key) + public static string GetString(string key) { - return PlayerPrefs.GetString(AddPrefix(key)); - } - - /** - * Returns true if a variable has been stored with this key. - */ - static public bool HasKey(string key) - { - return PlayerPrefs.HasKey(AddPrefix(key)); + if (String.IsNullOrEmpty(key) || + !stringDict.ContainsKey(key)) + { + return ""; + } + + return stringDict[key]; } /** * Stores a float variable using the key. */ - static public void SetFloat(string key, float value) + public static void SetFloat(string key, float value) { - PlayerPrefs.SetFloat(AddPrefix(key), value); + floatDict[key] = value; } /** * Stores an integer variable using the key. */ - static public void SetInteger(string key, int value) + public static void SetInteger(string key, int value) { - PlayerPrefs.SetInt(AddPrefix(key), value); + intDict[key] = value; } /** * Stores a boolean variable using the key. */ - static public void SetBoolean(string key, bool value) + public static void SetBoolean(string key, bool value) { - PlayerPrefs.SetInt(AddPrefix(key), value ? 1 : 0); + boolDict[key] = value; } /** * Stores a string variable using the key. */ - static public void SetString(string key, string value) + public static void SetString(string key, string value) { - PlayerPrefs.SetString(AddPrefix(key), value); + stringDict[key] = value; } /** * Replace keys in the input string with the string table entry. * Example format: "This {string_key} string" */ - static public string SubstituteStrings(string text) + public static string SubstituteStrings(string text) { string subbedText = text; @@ -146,7 +233,7 @@ namespace Fungus * Chops a string at the first new line character encountered. * This is useful for link / button strings that must fit on a single line. */ - static public string FormatLinkText(string text) + public static string FormatLinkText(string text) { string trimmed; if (text.Contains("\n")) @@ -160,15 +247,5 @@ namespace Fungus return trimmed; } - - static string AddPrefix(string key) - { - if (saveName.Length == 0) - { - return key; - } - - return saveName + "." + key; - } } } \ No newline at end of file