2

I create a simple Save Game system in Unity using Unity's JSON Serialization. My Save Game is pretty simple, I am only saving the position of my character and loading it.

The save game works fine, in-game. When I launch the game and click 'Save' the game is saved and the JSON file is updated with my players position. When I click 'Load' the game loads fine and my player is moved to the previously saved position.

However my issue is that whenever I shut down the game and relaunch it, the 'Load' function just resets my character to the position at which I spawn it at. It does not load the character at my previously saved position in the last game.

Now for my code. I have an Actor class which hold my actor's data:

using UnityEngine;
using System.Collections;
using System;

public class Actor : MonoBehaviour
{

    public ActorData data = new ActorData(); // to store our data

    public void StoreData() // for storing our data
    {
        data.pos = transform.position;
    }

    public void LoadData() // for loadinjg our data
    {
        transform.position = data.pos;
    }

    public void ApplyData()
    {
        SaveData.AddActorData(data);
    }

    void OnEnable() // to enable the save/load to avoid hanging
    {
        SaveData.OnLoaded += LoadData;
        SaveData.OnBeforeSave += StoreData;
        SaveData.OnBeforeSave += ApplyData;
    }

    void OnDisable() // to disable the save/load to avoid hanging
    {
        SaveData.OnLoaded -= LoadData;
        SaveData.OnBeforeSave -= StoreData;
        SaveData.OnBeforeSave -= ApplyData;
    }
}

[Serializable] // for storing in JSON
public class ActorData // our players attributes in JSON
{
    public Vector3 pos;
}

I also have an ActorContainer to hold the data for different players:

using System.Collections.Generic;
using System;

[Serializable]
public class ActorContainer
{

    // To store our different actors data
    public List<ActorData> actors = new List<ActorData>();
}

I have a SaveData class which performs my Serialization:

    using UnityEngine;
using System.Collections;
using System.IO;

public class SaveData
{

    // every actos will be sorted in this actor container when loading the game
    public static ActorContainer actorContainer = new ActorContainer(); // static so that we dont have to recreacte savedata everytime

    public delegate void SerializeAction();
    public static event SerializeAction OnLoaded; // happens after loading
    public static event SerializeAction OnBeforeSave; // right before saving

    public static void Load(string path) // where the load is
    {
        actorContainer = LoadActors(path);

        OnLoaded();

        ClearActorList(); // so that there's no duplicates
    }

    public static void Save(string path, ActorContainer actors)
    {
        OnBeforeSave(); // to throw of the data that was in OnBeforeSave

        SaveActors(path, actors); // store all of our actors as json in the file

        ClearActorList(); // clear the list so that the next time we save theres no duplicates
    }

    public static void AddActorData(ActorData data)
    {
        actorContainer.actors.Add(data);
    }

    public static void ClearActorList() // to avoid duplicate data
    {
        actorContainer.actors.Clear(); // access actors and clear it
    }

    private static ActorContainer LoadActors(string path) // path to the JSON
    {
        string json = File.ReadAllText(path); // loading all the text out of the file into a string, assuming the text is all JSON

        return JsonUtility.FromJson<ActorContainer>(json); // parse the JSON into an ActorContainer type and return in the LoadActors
    }

    private static void SaveActors(string path, ActorContainer actors) // where to save and the actors to save
    {
        string json = JsonUtility.ToJson(actors);

        StreamWriter sw = File.CreateText(path); // if file doesnt exist, make the file in the specified path
        sw.Close();

        File.WriteAllText(path, json); // fill the file with the data(json)
    }
}

Lastly I have a GameController class which acts as a communicator with Unity:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.IO;

public class GameController : MonoBehaviour
{ // to tell unity what it has to do, a communicator to be used with unity

    // trigger buttons
    public Button saveButton;
    public Button loadButton;

    private static string dataPath = string.Empty;

    void Awake()
    {
        dataPath = System.IO.Path.Combine(Application.persistentDataPath, "actors.json"); // persistentDataPath unity save game path, actors.json name of the file containing actors 
    }

    // for button
    public void Save()
    {
        SaveData.Save(dataPath, SaveData.actorContainer);
    }

    // for button 
    public void Load()
    {
        SaveData.Load(dataPath);
    }
}

My JSON file actors.json contains the following:

{"actors":[{"pos":{"x":419.6240539550781,"y":5.0189208984375,"z":0.0}}]}

Any suggestions are welcome.

arjwolf
  • 181
  • 4
  • 16

1 Answers1

1

So the problem is simply, you never assign the loaded Value from the JSON to data.pos in Actor.cs. Instead you load it from the public field ActorData data, which hasn't changed.

If i can see this right you have to change in Actor.cs following:

using System.Linq;

// ..

public void LoadData() 
{
    // guessing you will implementing an identifier for the separate actors later..
    var currentActor = SaveData.actorContainer.First();
    transform.position = currentActor.pos;

    // also set the loaded data to the field
    data = currentActor;
}

// ..