Unity3d Save Game (Json.Net)

So i was working on a game and i’m almost at the stage where sending alpha test builds out to people, then it hit me. You cannot save the game, that might prove difficult to people. Since my play testing only reached as far as testing a single feature at a time the saving and loading didnt really come to mind.
But here we are. I looked at Unity Serializer and it made no sense, not useful in anyway, it had more bugs than features, plus a project of that size would take longer to go over than to actually write my own that was tailored to my game. so here we go.
I have already started the save features.

What i have so far is:

using UnityEngine;
using System.Collections;

[System.Serializable]
public class State {

    public string Name;
    public int ID;
    public bool Active;
    public float[] Position = new float[3];
    public float[] Rotation = new float[3];

    public State() {
        // Used In loading
    }

    public State(GameObject Obj) {
        StoreObject(Obj);
    }

    public void StoreObject(GameObject Obj) {
        ID = Obj.GetInstanceID();
        Name = Obj.name;
        Active = Obj.activeSelf;
        Position[0] = Obj.transform.position.x;
        Position[1] = Obj.transform.position.y;
        Position[2] = Obj.transform.position.z;
        Rotation[0] = Obj.transform.rotation.x;
        Rotation[1] = Obj.transform.rotation.y;
        Rotation[2] = Obj.transform.rotation.z;
    }

}

This is the State Class that will keep the data we serialize on save. the control for this is this:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using System.IO;
using UnityEditor;

public class GameSave {
    public List<State> states = new List<State>();
}

public class GameState : MonoBehaviour {

    public List<State> states = new List<State>();

    public GameObject ObjectsToSave;

    List<GameObject> GetAllObjectsInScene() {
        List<GameObject> objectsInScene = new List<GameObject>();

        foreach(GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[]) {
            if (go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave)
                continue;

            string assetPath  = AssetDatabase.GetAssetPath(go.transform.root.gameObject);
            if (!string.IsNullOrEmpty(assetPath))
                continue;

            objectsInScene.Add(go);
        }

        return objectsInScene;
    }

    List<Component> AllNonStaticObjects() {
        List<Component> GameObjects = ObjectsToSave.GetComponentsInChildren(typeof(Transform), true).ToList();
        GameObjects = GameObjects.Where(o=>o.gameObject.isStatic == false).ToList();
        GameObjects.Add(GameObject.FindGameObjectWithTag("Player").transform);
        return GameObjects;
    }

    void Save_CurrentState() {
        states.Clear();
        List<Component> GameObjects = AllNonStaticObjects();
        foreach(Transform go in GameObjects) {
            states.Add(new State(go.gameObject));
        }
        //states.Add(GameObject.FindWithTag("Player"));
        GameSave NewSave = new GameSave();
        NewSave.states = states;
        File.WriteAllText(Application.dataPath + @"\Resources\mysave.json", JsonConvert.SerializeObject(NewSave));
    }

    void Load_LastState() {
        GameSave LoadSave = JsonConvert.DeserializeObject<GameSave>(File.ReadAllText(Application.dataPath + @"\Resources\mysave.json"));
        //states = LoadSave.states;
        List<Component> GameObjects = AllNonStaticObjects();
        foreach(Transform g in GameObjects) {
            var ObjState = LoadSave.states.Where(o=>o.ID==g.gameObject.GetInstanceID()).FirstOrDefault();
            if(ObjState != null){
            try { 
                if(g.gameObject.activeSelf) {
                  g.gameObject.transform.position = new Vector3(ObjState.Position[0], ObjState.Position[1], ObjState.Position[2]);
                  g.gameObject.transform.rotation = new Quaternion(ObjState.Rotation[0], ObjState.Rotation[1], ObjState.Rotation[2], 0);
                }
                g.gameObject.SetActive(ObjState.Active);
            } catch {
                Debug.Log(g.name);
            }
            } else {
                Debug.Log("No State Found For Object Name: " + g.name);
            }
        }
    }

    void Update () {
         if(Input.GetKeyUp(KeyCode.M)) {
            Load_LastState();
        }
        if(Input.GetKeyUp(KeyCode.O)) {
            Save_CurrentState();
        }
    }
}

So what does all this nonsense mean? well, i am using the json.net serializer to save the object to a json file
and i use the keys “O” to save and “M” why, because adding buttons takes to long when im in the testing phase.

We get all children of the master parent if you can call it that, which only has objects that can move in the game world
a.k.a non-static objects. When we have a list of all those objects stored in the SaveGame Class we then serialize the object
to a json file and back again when we load it.

Im not done with the save/load feature of the game yet, i am currently only keeping track of the position, rotation and if the object is active in game space.
i also have to check variables in attaches scripts and what not, so that should be done within the next few hours.

Im not really posting the entire source of the game here, or this feature 😛 just thought it would give people and idea of how to do the load/save feature
in unity using C# since there are a lot of posts of people asking how this can be done. and i like the dynamic nature of this method.

Leave a comment