- Home /
Serialised data not saving on reload
Hi, I'm making a rhythm game and I'm using a serialised data system. When the player completes a level, I want to check whether their currentScore is greater than their level1PersonalBest (their saved high score) and whether their currentHighestCombo is greater than their level1HighestCombo (their saved highest combo). If so, the save system should overwrite the stored values with these values. When I complete the level, I have a series of Debug.Log messages that tell me whether level1PersonalBest or level1HighestCombo were overwritten.
The issue is that, when I load the scene again, the values of level1PersonalBest and level1HighestCombo appear to have been reset to 0 (as indicated by the Debug.Log message that executes in the Start function of the GameManager). I assume its a problem related to how I'm instantiating the PlayerData class in the GameManager?
Data that the SaveSystem is saving:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PlayerData
{
public int level1PersonalBest;
public int level1HighestCombo;
public void SetPersonalBest(int currentScore)
{
level1PersonalBest = currentScore;
}
public void SetHighestCombo(int currentHighestCombo)
{
level1HighestCombo = currentHighestCombo;
}
public void ResetData()
{
level1PersonalBest = 0;
level1HighestCombo = 0;
}
}
The SaveSystem class:
using UnityEngine;
using System.IO; //Used for creating and opening the save file
using System.Runtime.Serialization.Formatters.Binary; //Used for converting save data in and out of binary
public class SaveSystem : MonoBehaviour
{
static public SaveSystem instance;
string filePath;
private void Awake()
{
if (!instance) //Check there are no other instances of this class in the scene
{
instance = this;
}
else
{
Destroy(gameObject);
}
filePath = Application.persistentDataPath + "/save.data";
//Gets a path to a data directory on the player's device that cannot be altered (e.g. avoiding user-created folders)
//Creates a file within the directory named 'save.data'
}
public void saveData(PlayerData data)
{
FileStream fileStream = new FileStream(filePath, FileMode.Create);
//The filestream is a stream of data contained in the save file
//This code creates a file on the user's device using the savePath defined above
BinaryFormatter converter = new BinaryFormatter();
//Create a binary formatter to convert the save data to binary
converter.Serialize(fileStream, data); //Converts the data to binary and adds it to the file
fileStream.Close(); //Close off the files once data has been added
}
public PlayerData loadData()
{
if (File.Exists(filePath))
{
FileStream fileStream = new FileStream(filePath, FileMode.Open);
BinaryFormatter converter = new BinaryFormatter();
PlayerData data = converter.Deserialize(fileStream) as PlayerData;
fileStream.Close();
return data;
}
else
{
Debug.LogError("Save file not found in " + filePath);
return null;
}
}
}
My GameManager class (attached to the same object as the SaveSystem script): (Some parts completely unrelated to the save system have been cut out of this snippet)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
PlayerData data = new PlayerData();
public float songBpm; //This is determined by the song you're trying to sync up to
public float secPerBeat; //The number of seconds for each song beat
public float songPositionInSeconds; //Current song position, in seconds
public float songPositionInBeats; //Current song position, in beats
public float offset; //How long it took for the music to start
public AudioSource music; //An AudioSource attached to this GameObject that will play the music
public AudioSource missedSoundEffect;
public bool levelHasStarted = false, levelHasEnded = false;
public CameraShake cameraShake;
public NoteSpawner noteSpawner;
public PlayFabManager playFabManager;
public GameObject startMessageScreen, scoreAndCombo, resultsScreenBackground, levelFailedScreen;
public ResultsScreenManager resultsScreenManager;
public TMPro.TMP_Text levelFailedScoreText;
public int currentScore = 0, currentHighestCombo = 0, currentMultiplier, currentCombo = 0, multiplierTracker = 0;
public int[] multiplierThresholds; //Stores the required combo to reach the next multiplier level
public int totalNotes, missedHits, okayHits, goodHits, perfectHits;
public Text scoreText, comboText;
// Start is called before the first frame update
void Start()
{
instance = this;
scoreText.text = "0";
currentMultiplier = 1;
AudioListener.pause = false;
Debug.Log("Personal best: " + data.level1PersonalBest + " , Highest Combo: " + data.level1HighestCombo);
}
// Update is called once per frame
void Update()
{
if (PauseMenuManager.GameIsPaused == true)
{
music.Pause();
}
else
{
music.UnPause();
}
if (levelHasStarted == false)
{
if (Input.anyKeyDown) //And if any key is pressed...
{
startMessageScreen.SetActive(false);
scoreAndCombo.SetActive(true);
secPerBeat = 60f / songBpm; //Calculate the number of seconds per beat
offset = (float)AudioSettings.dspTime; //Record the time when the music starts
music.Play(); //And start playing the music
levelHasStarted = true;
}
}
else if (levelHasStarted == true && music.isPlaying == true && PauseMenuManager.GameIsPaused == false && levelHasEnded == false)
{
songPositionInSeconds = (float)(AudioSettings.dspTime - offset); //Calculate how many seconds since the song started
songPositionInBeats = (songPositionInSeconds / secPerBeat) + 1; //Calculate how many beats since the song started
}
else if (levelHasStarted == true && music.isPlaying == false && PauseMenuManager.GameIsPaused == false && levelHasEnded == false)
//Check if the music has finished playing and the level has ended
{
if (currentScore > data.level1PersonalBest) //Compare the current score of the player to the stored PersonalBest score
{
Debug.Log("Personal best of " + data.level1PersonalBest + " has been beaten by current score of " + currentScore);
data.SetPersonalBest(currentScore);
SaveSystem.instance.saveData(data);
//If the player has beaten their PersonalBest,
//Call the saveData function of the static SaveSystem class, passing in the score of this gameManager object
//This will overwrite their PersonalBest with their current score
Debug.Log("Personal best has successfully saved as " + data.level1PersonalBest);
playFabManager.SendLeaderboard(currentScore);
//This will update the leaderboard with the player's final score
}
else
Debug.Log("Personal best of " + data.level1PersonalBest + " has not been beaten by the current score of " + currentScore);
if (currentHighestCombo > data.level1HighestCombo)
{
Debug.Log("Personal highest combo of " + data.level1HighestCombo + " has been beaten by current highest combo of " + currentHighestCombo);
data.SetHighestCombo(currentHighestCombo);
SaveSystem.instance.saveData(data);
Debug.Log("Personal highest combo has successfully saved as " + data.level1HighestCombo);
}
else
Debug.Log("Personal highest combo of " + data.level1HighestCombo + " has not beaten by the current highest combo of " + currentHighestCombo);
resultsScreenManager.InitialiseResultsScreen();
//This will set the values of the text elements of the results screen and enable it
levelHasEnded = true; //Prevent the results screen from being initialised every frame
}
}
You can probably ignore all the code directly related to the rhythm game mechanics. As I said, the rest of the game is working as intended. You can also ignore the comments, those are for myself more than anything.
If you need any more information, feel free to ask. Thanks!
Your answer

Follow this Question
Related Questions
Error: GetComponentFastPath is not allowed? 2 Answers
DrawDefaultEditor causing field to be serialized multiple times? 1 Answer
Problem with serialization since version 5.0 (Parent/Children relationship) 0 Answers
does this key not found error have to do with serialization? 2 Answers
[Solved]How to serialize Dictionary with Unity Serialization System 6 Answers