- Home /
How to set and save individual highscores for each scene using serialization?
I have followed the Unity live tutorial on Data Persistence as I understand it is much better than PlayerPrefs for saving scores etc. However, I find that the high score that I saved in Scene 1 persists into my other scenes. How would I go about setting and saving separate high scores with my serialization script?
Answer by Munchy2007 · Jan 12, 2016 at 10:11 AM
You just need to give each scene its own high score entry in your saved data and then load the corresponding entry when each scene loads.
PseudoCode...
void SaveScore()
{
SceneNameHiScore = sceneHiScore;
SceneNameHiScore.Save();
}
void OnSceneWasLoaded()
{
sceneHiScore = SceneNameHiScore.Load();
}
Answer by Munchy2007 · Jan 12, 2016 at 08:26 PM
Here's a quick implementation of a class for saving and loading an array of high scores. You can access the individual scores by level number.
using UnityEngine;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
[System.Serializable]
public class PlayerData {
int[] hiScores;
public int maxLevels {
get;
set;
}
protected PlayerData()
{
}
public PlayerData (int maxLevels)
{
this.maxLevels = maxLevels;
hiScores = new int[maxLevels];
}
public void SetScore(int levelNumber, int score)
{
hiScores[levelNumber] = score;
}
public int GetScore(int levelNumber)
{
return hiScores[levelNumber];
}
public void Save(string path)
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(path);
bf.Serialize(file, this);
file.Close();
}
public static PlayerData Load(string path)
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(path, FileMode.Open);
PlayerData data = (PlayerData)bf.Deserialize(file);
file.Close();
return data;
}
}
For simplicity the array size is set when you create an instance of the class, but this could be improved on to make it dynamic.
Put this test script on an empty game object and it should debug.log 50 scores.
using UnityEngine;
using System.Collections;
public class TestPlayerData : MonoBehaviour {
// Use this for initialization
void Start () {
PlayerData playerData = new PlayerData(50);
// Insert some test data
for(int levelNum=0; levelNum< playerData.maxLevels; levelNum++)
{
playerData.SetScore(levelNum, (levelNum+1) * Random.Range(500,1000));
}
Debug.Log("Saving data...");
playerData.Save(Application.persistentDataPath + "/PlayerInfo.dat");
Debug.Log("Loading data...");
playerData = PlayerData.Load(Application.persistentDataPath + "/PlayerInfo.dat");
for(int levelNum = 0; levelNum<50;levelNum++)
{
Debug.Log(playerData.GetScore(levelNum));
}
}
// Update is called once per frame
void Update () {
}
}
Hopefully this is of some help to you :)
That's fabulous, thanks a lot! Hopefully it'll be helpful to other people too!
Answer by Strangerweather · Jan 12, 2016 at 01:29 PM
Many thanks for your reply! I am still a bit confused. This is what I did:
public void Save ()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat");
PlayerData data = new PlayerData();
data.highScore1 = highScore1;
data.highScore2 = highScore2;
data.highScore3 = highScore3;
bf.Serialize(file, data);
file.Close();
}
public void Load()
{
if (File.Exists(Application.persistentDataPath+ "/playerInfo.dat"))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/playerInfo.dat", FileMode.Open);
PlayerData data = (PlayerData)bf.Deserialize(file);
file.Close();
highScore1 = data.highScore1;
highScore2 = data.highScore2;
highScore3 = data.highScore3;
}
}
The problem is my ScoreManager:
void Start()
{
GameControl.control.Load();
highScoreText.text = "High Score: " + Mathf.Round(GameControl.control.highScore);
}
void Update()
{
if (scoreIncreasing)
{
scoreCount += minusPointsPerSecond * Time.deltaTime;
}
scoreText.text = "Score: " + Mathf.Round(scoreCount);
}
public void SetHighScore()
{
if (scoreCount > GameControl.control.highScore)
{
GameControl.control.highScore = scoreCount;
}
highScoreText.text = "High Score: " + Mathf.Round(GameControl.control.highScore);
GameControl.control.Save();
}
Do I also need 3 separate scoreCounts and 3 separate scoreTexts? And finally, how can I associate the scenes with the highscores? Is it done manually in the Inspector?
You should only need the one scoreText and scoreCount as these are look like they are just used to handle the score within the current level.
What you do need is some way to associate each scene with the appropriate entry in your PlayerData class.
You haven't posted your PlayerData class implementation, but from your code it doesn't look like it easily lends itself to doing what you want.
I think if I was doing it, I would use a string,int dictionary to store the high scores, with the key being the scene name. If you need more help with this let me know and I'll see if I can throw a quick example together.
Thanks so much that's very kind of you. It would be great if you could throw a quick example together as you suggest because I have been trying to do exactly that for days and I am not getting anywhere. Also, I have read that dictionaries can't be serialized. Will that not be a problem? Thanks again!
That's very true, I forgot about that, although there are some solutions to dictionary serialisation kicking around (http://answers.unity3d.com/questions/460727/how-to-serialize-dictionary-with-unity-serializati.html). However, in this instance it would probably be easier to implement the PlayerData class differently, so that it can be serialised.
I'm leaving work in a few $$anonymous$$utes, so I'll have to wait until I get home before I can take another look at it. Unless anyone else provides a solution in the meantime I'll see if I can work out a reasonably elegant solution a bit later tonight.
Your answer
![](https://koobas.hobune.stream/wayback/20220612055917im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Displaying highscore in the main menu scene 1 Answer
Serialized data not getting saved in iPhone 1 Answer
Local High-Scores with PlayerPrefs? 1 Answer
Unity Serializer scripting error 1 Answer
Saving using Serialization and IDs 0 Answers