diff --git a/Assets/Fungus/Scripts/Commands/SavePoint.cs b/Assets/Fungus/Scripts/Commands/SavePoint.cs index b3dfcc39..e2d4a45f 100644 --- a/Assets/Fungus/Scripts/Commands/SavePoint.cs +++ b/Assets/Fungus/Scripts/Commands/SavePoint.cs @@ -2,8 +2,6 @@ // It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) using UnityEngine; -using System.Collections; -using UnityEngine.SceneManagement; namespace Fungus { diff --git a/Assets/Fungus/Scripts/Components/SaveData.cs b/Assets/Fungus/Scripts/Components/SaveData.cs index 750748c7..280b8651 100644 --- a/Assets/Fungus/Scripts/Components/SaveData.cs +++ b/Assets/Fungus/Scripts/Components/SaveData.cs @@ -4,38 +4,60 @@ using System.Collections.Generic; namespace Fungus { /// - /// Contains a list of game objects whose state will be saved for each Save Point. + /// This component encodes and decodes a list of game objects to be saved for each Save Point. + /// It knows how to encode / decode concrete game classes like Flowchart and FlowchartData. + /// To extend the save system to handle other data types, just modify or subclass this component. /// public class SaveData : MonoBehaviour { + protected const string FlowchartDataKey = "FlowchartData"; + [Tooltip("A list of Flowchart objects whose variables will be encoded in the save data. Boolean, Integer, Float and String variables are supported.")] [SerializeField] protected List flowcharts = new List(); #region Public methods /// - /// Encodes the list of Flowcharts and adds it to a Save Point Data object. - /// - public void Encode(SavePointData savePointData) + /// Encodes the objects to be saved as a list of SaveDataItems. + /// saveDataItems) { for (int i = 0; i < flowcharts.Count; i++) { var flowchart = flowcharts[i]; var flowchartData = FlowchartData.Encode(flowchart); - savePointData.FlowchartDatas.Add(flowchartData); + + var saveDataItem = SaveDataItem.Create(FlowchartDataKey, JsonUtility.ToJson(flowchartData)); + + saveDataItems.Add(saveDataItem); } } /// - /// Decodes the Flowchart data from the save point data. + /// Decodes the loaded list of SaveDataItems to restore the saved game state. /// - public void Decode(SavePointData savePointData) + public virtual void Decode(List saveDataItems) { - for (int i = 0; i < savePointData.FlowchartDatas.Count; i++) + for (int i = 0; i < saveDataItems.Count; i++) { - var flowchartData = savePointData.FlowchartDatas[i]; - FlowchartData.Decode(flowchartData); - } + var saveDataItem = saveDataItems[i]; + if (saveDataItem == null) + { + continue; + } + + if (saveDataItem.DataType == FlowchartDataKey) + { + var flowchartData = JsonUtility.FromJson(saveDataItem.Data); + if (flowchartData == null) + { + Debug.LogError("Failed to decode Flowchart save data item"); + return; + } + + FlowchartData.Decode(flowchartData); + } + } } #endregion diff --git a/Assets/Fungus/Scripts/Components/SaveManager.cs b/Assets/Fungus/Scripts/Components/SaveManager.cs index b47734bc..41fafe76 100644 --- a/Assets/Fungus/Scripts/Components/SaveManager.cs +++ b/Assets/Fungus/Scripts/Components/SaveManager.cs @@ -1,5 +1,7 @@ -using UnityEngine; -using System.Collections; +// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). +// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) + +using UnityEngine; using UnityEngine.SceneManagement; namespace Fungus diff --git a/Assets/Fungus/Scripts/Editor/SaveData.cs b/Assets/Fungus/Scripts/Editor/SaveDataEditor.cs similarity index 100% rename from Assets/Fungus/Scripts/Editor/SaveData.cs rename to Assets/Fungus/Scripts/Editor/SaveDataEditor.cs diff --git a/Assets/Fungus/Scripts/Editor/SaveData.cs.meta b/Assets/Fungus/Scripts/Editor/SaveDataEditor.cs.meta similarity index 100% rename from Assets/Fungus/Scripts/Editor/SaveData.cs.meta rename to Assets/Fungus/Scripts/Editor/SaveDataEditor.cs.meta diff --git a/Assets/Fungus/Scripts/Utils/FlowchartData.cs b/Assets/Fungus/Scripts/Utils/FlowchartData.cs index 25bc493c..d1fe8485 100644 --- a/Assets/Fungus/Scripts/Utils/FlowchartData.cs +++ b/Assets/Fungus/Scripts/Utils/FlowchartData.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). +// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) + +using System.Collections.Generic; using UnityEngine; namespace Fungus diff --git a/Assets/Fungus/Scripts/Utils/SaveDataItem.cs b/Assets/Fungus/Scripts/Utils/SaveDataItem.cs new file mode 100644 index 00000000..16bb0368 --- /dev/null +++ b/Assets/Fungus/Scripts/Utils/SaveDataItem.cs @@ -0,0 +1,45 @@ +// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). +// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) + +using UnityEngine; + +namespace Fungus +{ + /// + /// A container for a single unity of saved data. + /// The data and its associated type are stored as string properties. + /// The data would typically be a JSON string representing a saved object. + /// + [System.Serializable] + public class SaveDataItem + { + [SerializeField] protected string dataType = ""; + [SerializeField] protected string data = ""; + + #region Public methods + + /// + /// Gets the type of the data. + /// + public virtual string DataType { get { return dataType; } } + + /// + /// Gets the data. + /// + public virtual string Data { get { return data; } } + + /// + /// Factory method to create a new SaveDataItem. + /// + public static SaveDataItem Create(string dataType, string data) + { + var item = new SaveDataItem(); + item.dataType = dataType; + item.data = data; + + return item; + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Fungus/Scripts/Utils/SaveDataItem.cs.meta b/Assets/Fungus/Scripts/Utils/SaveDataItem.cs.meta new file mode 100644 index 00000000..a9c855e9 --- /dev/null +++ b/Assets/Fungus/Scripts/Utils/SaveDataItem.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 67dfa5e8ded9244f98136428ed129403 +timeCreated: 1484649086 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Scripts/Utils/SavePointData.cs b/Assets/Fungus/Scripts/Utils/SavePointData.cs index 7e811a59..fec9d927 100644 --- a/Assets/Fungus/Scripts/Utils/SavePointData.cs +++ b/Assets/Fungus/Scripts/Utils/SavePointData.cs @@ -1,43 +1,25 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; -using System.Collections; +using UnityEngine.Events; namespace Fungus { /// - /// Serializable container for a Save Point. + /// Serializable container for a Save Point's data. + /// All data is stored as strings, and the only concrete game class it depends on is the SaveData component. /// [System.Serializable] public class SavePointData { [SerializeField] protected string savePointKey; - [SerializeField] protected string savePointDescription; - [SerializeField] protected string sceneName; - [SerializeField] protected List flowchartDatas = new List(); - protected static SavePointData tempSavePointData; + [SerializeField] protected string savePointDescription; - protected static void OnSceneLoaded(Scene scene, LoadSceneMode mode) - { - // Additive scene loads and non-matching scene loads could happen if someone is using - // Fungus as part of a bigger game, so just ignore these events and hope they know what they're doing. - if (mode == LoadSceneMode.Additive || - scene.name != tempSavePointData.SceneName) - { - return; - } - SceneManager.sceneLoaded -= OnSceneLoaded; + [SerializeField] protected string sceneName; - var saveDatas = GameObject.FindObjectsOfType(); - foreach (var saveData in saveDatas) - { - saveData.Decode(tempSavePointData); - } + [SerializeField] protected List saveDataItems = new List(); - SaveManagerSignals.DoSavePointLoaded(tempSavePointData.savePointKey); - } - protected static SavePointData Create(string _savePointKey, string _savePointDescription, string _sceneName) { var savePointData = new SavePointData(); @@ -67,9 +49,10 @@ namespace Fungus public string SceneName { get { return sceneName; } set { sceneName = value; } } /// - /// Gets or sets the encoded Flowchart data for the Save Point. + /// Gets the list of save data items. /// - public List FlowchartDatas { get { return flowchartDatas; } set { flowchartDatas = value; } } + /// The save data items. + public List SaveDataItems { get { return saveDataItems; } } /// /// Encodes a new Save Point to data and converts it to JSON text format. @@ -77,11 +60,12 @@ namespace Fungus public static string Encode(string _savePointKey, string _savePointDescription, string _sceneName) { var savePointData = Create(_savePointKey, _savePointDescription, _sceneName); - - var saveDatas = GameObject.FindObjectsOfType(); - foreach (var saveData in saveDatas) + + // Look for a SaveData component in the scene to populate the save data items. + var saveData = GameObject.FindObjectOfType(); + if (saveData != null) { - saveData.Encode(savePointData); + saveData.Encode(savePointData.SaveDataItems); } return JsonUtility.ToJson(savePointData, true); @@ -92,10 +76,33 @@ namespace Fungus /// public static void Decode(string saveDataJSON) { - tempSavePointData = JsonUtility.FromJson(saveDataJSON); - - SceneManager.sceneLoaded += OnSceneLoaded; - SceneManager.LoadScene(tempSavePointData.SceneName); + var savePointData = JsonUtility.FromJson(saveDataJSON); + + UnityAction onSceneLoadedAction = null; + + onSceneLoadedAction = (scene, mode) => { + // Additive scene loads and non-matching scene loads could happen if the client is using the + // SceneManager directly. We just ignore these events and hope they know what they're doing! + if (mode == LoadSceneMode.Additive || + scene.name != savePointData.SceneName) + { + return; + } + + SceneManager.sceneLoaded -= onSceneLoadedAction; + + // Look for a SaveData component in the scene to process the save data items. + var saveData = GameObject.FindObjectOfType(); + if (saveData != null) + { + saveData.Decode(savePointData.SaveDataItems); + } + + SaveManagerSignals.DoSavePointLoaded(savePointData.savePointKey); + }; + + SceneManager.sceneLoaded += onSceneLoadedAction; + SceneManager.LoadScene(savePointData.SceneName); } #endregion