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?

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();
}

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 :slight_smile:

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?