Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using Newtonsoft.Json;
- using UnityEngine;
- using UnityEngine.SceneManagement;
- namespace GameDevTV.Saving
- {
- /// <summary>
- /// This component provides the interface to the saving system. It provides
- /// methods to save and restore a scene.
- ///
- /// This component should be created once and shared between all subsequent scenes.
- /// </summary>
- public class SavingSystem : MonoBehaviour
- {
- /// <summary>
- /// Will load the last scene that was saved and restore the state. This
- /// must be run as a coroutine.
- /// </summary>
- /// <param name="saveFile">The save file to consult for loading.</param>
- public IEnumerator LoadLastScene(string saveFile)
- {
- Dictionary<string, object> state = LoadFile(saveFile);
- int buildIndex = SceneManager.GetActiveScene().buildIndex;
- if (state.ContainsKey("lastSceneBuildIndex"))
- {
- buildIndex = state["lastSceneBuildIndex"].ToInt();
- }
- yield return SceneManager.LoadSceneAsync(buildIndex);
- RestoreState(state);
- }
- /// <summary>
- /// Save the current scene to the provided save file.
- /// </summary>
- public void Save(string saveFile)
- {
- Dictionary<string, object> state = LoadFile(saveFile);
- CaptureState(state);
- SaveFile(saveFile, state);
- }
- /// <summary>
- /// Delete the state in the given save file.
- /// </summary>
- public void Delete(string saveFile)
- {
- File.Delete(GetPathFromSaveFile(saveFile));
- }
- public void Load(string saveFile)
- {
- RestoreState(LoadFile(saveFile));
- }
- // PRIVATE
- private Dictionary<string, object> LoadFile(string saveFile)
- {
- string path = GetPathFromSaveFile(saveFile);
- if (!File.Exists(path))
- {
- return new Dictionary<string, object>();
- }
- using (StreamReader file = File.OpenText(path))
- {
- JsonSerializer serializer = new JsonSerializer();
- serializer.TypeNameHandling = TypeNameHandling.All;
- serializer.Formatting = Formatting.Indented;
- serializer.FloatParseHandling = FloatParseHandling.Double;
- return (Dictionary<string, object>) serializer.Deserialize(file, typeof(Dictionary<string, object>));
- }
- //using (FileStream stream = File.Open(path, FileMode.Open))
- //{
- // BinaryFormatter formatter = new BinaryFormatter();
- // return (Dictionary<string, object>)formatter.Deserialize(stream);
- //}
- }
- private void SaveFile(string saveFile, object state)
- {
- string path = GetPathFromSaveFile(saveFile);
- print("Saving to " + path);
- using (StreamWriter file = File.CreateText(path))
- {
- JsonSerializer serializer = new JsonSerializer();
- serializer.TypeNameHandling = TypeNameHandling.All;
- serializer.Formatting = Formatting.Indented;
- serializer.FloatParseHandling = FloatParseHandling.Double;
- serializer.Serialize(file, state);
- }
- //using (FileStream stream = File.Open(path, FileMode.Create))
- //{
- // BinaryFormatter formatter = new BinaryFormatter();
- // formatter.Serialize(stream, state);
- //}
- }
- private void CaptureState(Dictionary<string, object> state)
- {
- foreach (SaveableEntity saveable in FindObjectsOfType<SaveableEntity>())
- {
- state[saveable.GetUniqueIdentifier()] = saveable.CaptureState();
- }
- state["lastSceneBuildIndex"] = SceneManager.GetActiveScene().buildIndex;
- }
- private void RestoreState(Dictionary<string, object> state)
- {
- foreach (SaveableEntity saveable in FindObjectsOfType<SaveableEntity>())
- {
- string id = saveable.GetUniqueIdentifier();
- if (state.ContainsKey(id))
- {
- saveable.RestoreState(state[id]);
- }
- }
- }
- private string GetPathFromSaveFile(string saveFile)
- {
- return Path.Combine(Application.persistentDataPath, saveFile + ".json");
- }
- }
- public static class SavingHelpers
- {
- /// <summary>
- /// Converts an object that has been decoded by JSon.Net For Unity into a float. Will succeed if the object was deserialized as a double, float, or int64
- /// </summary>
- /// <param name="o">object that has been deserialized by Json.Net For Unity</param>
- /// <returns></returns>
- public static float ToFloat(this object o)
- {
- switch (o)
- {
- case double d: return (float) d;
- case float f: return f;
- case int i: return i;
- case Int64 q: return (float) q;
- default: return 0.0f;
- }
- }
- /// <summary>
- /// Converts an object that has been decoded by JSon.Net For Unity into an int. Will succeed if the object was deserialized as a double, float, or int64.
- /// Float and double values will be truncated automatically.
- /// </summary>
- /// <param name="o">object that has been deserialized by Json.Net For Unity</param>
- /// <returns></returns>
- public static int ToInt(this object o)
- {
- switch (o)
- {
- case double d: return Mathf.FloorToInt((float) d);
- case float f: return Mathf.FloorToInt(f);
- case int i: return i;
- case Int64 q: return (int) q;
- default: return 0;
- }
- }
- /// <summary>
- /// Returns an object for JSon.Net for Unity to Serialize.
- /// </summary>
- /// <param name="v"></param>
- /// <returns></returns>
- public static object ToObject(this Vector3 v)
- {
- return new List<float> { v.x, v.y, v.z};
- }
- /// <summary>
- /// Converts and object that was deserialized as a Vector3 by JSon.Net to a bonafide Vector3.
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- public static Vector3 ToVector3(this object o)
- {
- Vector3 v = Vector3.zero;
- if (o is IList l)
- {
- if (l.Count == 3)
- {
- v.x = l[0].ToFloat();
- v.y = l[1].ToFloat();
- v.z = l[2].ToFloat();
- }
- }
- return v;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement