BinaryFormatter Saves Data Between Scenes But Reset After Quitting the App

I created a Saving System similar to the one in Brackey’s tutorial. It keeps data between scenes but the data gets reset after restarting the app. How can I keep the data even after restarting the game?

public class PlayerData : MonoBehaviour
{
    public static bool playerisSaved;
    private bool isfirstSaveExist;
    
    public static bool itemBought{get;set;}
    public static int totalCoinAmount{get;set;}
    public static int selectedCar{get;set;}
    public static int  selectedCarColor{get;set;}
    public static int selectedSpoiler{get;set;}
    public static int selectedSpoilerColor{get;set;}
    public static int selectedNeonColor{get;set;}
    public static int selectedWheelColor{get;set;}


    public int spoilerSave;
    public int spoilerColorSave;
    public int neonColorSave;
    public int carColorSave;
    public int wheelColorSave;
    public int coinSave;
    public int carSave;
    public int currentLevel;
    
    void Start()
    {
          playerisSaved = false;
          if(isfirstSaveExist == true)
        {
            LoadPlayer();
        }
       
    }

    public void SavePlayer()
    {
        PlayerDataSaver.SavePlayer(this);
    }

   public void LoadPlayer()
   {
      PlayerDataHandler data = PlayerDataSaver.LoadPlayer();
      currentLevel = data.Level;
      totalCoinAmount= data.Coin;
      if(itemBought == true)
      {
        selectedCar = data.PickedCar;
      }
   }
  
  void Update()
  {
    coinSave = totalCoinAmount;
    carSave= selectedCar;
    spoilerSave = selectedSpoiler;
    spoilerColorSave = selectedSpoilerColor;
    neonColorSave = selectedNeonColor;
    carColorSave = selectedCarColor;
    wheelColorSave = selectedWheelColor;
    SaveReciver();
  }
public void SaveReciver()
{
        if(playerisSaved == true)
    {
       SavePlayer();
       isfirstSaveExist = true;
       playerisSaved = false; 
    }
}

  void OnApplicationQuit()
  {
    SavePlayer();
  }

}



[System.Serializable]
public class PlayerDataHandler
{   
public int Level {get; set;}
public int Coin{get; set;}
public int PickedCar{get; set;}
public int CarColor{get; set;}
public int NeonColor{get; set;}
public int Spoiler{get; set;}
public int SpoilerColor{get; set;}
public int WheelColor{get; set;}

public static PlayerDataHandler FromPlayerData(PlayerData player)
{
    return new PlayerDataHandler
    {
 Coin = player.coinSave,
 Level = player.currentLevel,
 PickedCar = player.carSave,
 CarColor = player.carColorSave,
 NeonColor = player.neonColorSave,
 Spoiler = player.spoilerSave,
 SpoilerColor = player.spoilerColorSave,
 WheelColor = player.wheelColorSave,
    };
}
}

using System.IO;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
public static class PlayerDataSaver 
{
public static void SavePlayer(PlayerData player)
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/player.data";
FileStream stream = new FileStream(path, FileMode.Create);

PlayerDataHandler data =  PlayerDataHandler.FromPlayerData(player);
formatter.Serialize(stream, data);
stream.Close();
}

public static PlayerDataHandler LoadPlayer()
{
   string path = Application.persistentDataPath +"/player.data";
   if(File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path,FileMode.Open);
PlayerDataHandler data = formatter.Deserialize(stream) as PlayerDataHandler;
stream.Close();
return data;
} 
else
{
    Debug.LogError("Save file not found in "+path);
    return null;
}
}
}

Hello there, I myself have been messing with saving/loading data recently and have learned some things through research so I hope I can help you. First off, from my understanding, you don’t want to use binary serialization as it is not secure and cannot be made to be secure.

Reference for that:

Here is what I do for saving in my game and I will use your variables that you have provided in place of mine. First thing I would do is make a Script that controls all of the values you want and name it so it matches what you are trying to achieve. Don’t feel like you have to put all data you want saved into one script, use multiple for the different aspects of your game. In this case I will call it PlayerCarDetails. I will only use 3 variables as strings but you can add more and use them as ints, floats, etc. and it will still apply all the same.

using UnityEngine;

public class PlayerCarDetails : MonoBehaviour
{
    public int selectedCar;
    public int carColor;
    public int carWheelColor;
}

Then we will take your PlayerDataHandler Script and use it to set up our details we want to save. We will use the same variable names to avoid confusion as to what they do. We will then make a PlayerDataHandler method to get the details we want from our PlayerCarDetails Script. In this method we will match the variables to the ones in the car details script.

[System.Serializable]
public class PlayerDataHandler
{
    public int selectedCar;
    public int carColor;
    public int carWheelColor;

    public PlayerDataHandler (PlayerCarDetails playerCarDetails)
    {
        selectedCar = playerCarDetails.selectedCar;
        carColor = playerCarDetails.carColor;
        carWheelColor = playerCarDetails.carWheelColor;
    }
}

Next we will make our SaveGame Script. Here we will be using Json instead of BinaryFormatter. To simply sum up what is happening in the SavePlayerCar method, we are taking the details from our PlayerDataHandler Script, turning them into Json format, then writing those details to our save path which will save the file on the players computer. In the LoadPlayerCar method we are seeing if the file exists already and if it does we are converting it back from Json into something unity can read and it will be returned back to the script that needs it (which will be in the next section). If there is no save file already we are logging an error and returning nothing.

using System.IO;
using UnityEngine;

public class SaveGame
{
    public static void SavePlayerCar(PlayerCarDetails playerCarDetails)
    {
        string savePath = Application.persistentDataPath + "/CarDetails.Save";
        string json = JsonUtility.ToJson(playerCarDetails);

        using StreamWriter writer = new StreamWriter(savePath);
        writer.Write(json);

        Debug.Log("Game Saved!");
    }

    public static PlayerDataHandler LoadPlayerCar()
    {
        string savePath = Application.persistentDataPath + "CarDetails.Save";

        if (File.Exists(savePath))
        {
            using StreamReader reader = new StreamReader(savePath);
            string json = reader.ReadToEnd();

            PlayerDataHandler data = JsonUtility.FromJson<PlayerDataHandler>(json);

            return data;
        }

        else
        {
            Debug.LogError("Error: No save file found in " + savePath);
            return null;
        }
    }

Finally we will go back to our PlayerCarDetails Script and use this information that has been saved, or initialize it if it has not been saved and then save the initialized values. We will do so in our Start method. We are also adding our Save method in here so we can save the data we want. I also added a Debug.Log statement so we can see in the console that our data was loaded and what was loaded.

using UnityEngine;

public class PlayerCarDetails : MonoBehaviour
{
    public string selectedCar;
    public string carColor;
    public string carWheelColor;

    private void Start()
    {
        PlayerDataHandler data = SaveGame.LoadPlayerCar();

        if (data == null)
        {
            selectedCar = "Honda Civic";
            carColor = "Blue";
            carWheelColor = "Silver";
            Save();
        }

        else
        {
            selectedCar = data.selectedCar;
            carColor = data.carColor;
            carWheelColor = data.carWheelColor;
        }

        Debug.Log($"{selectedCar}, {carColor}, {carWheelColor}");
    }

    public void Save()
    {
        SaveGame.SavePlayerCar(this);
    }
}

I hope this helps you achieve what you want, if you have further questions feel free to ask!