How to Save Game Data on Unity

Servet Gulnaroglu
3 min readSep 1, 2021

In unity, we can save the game data with three scripts. What I mean by game data is that the progress of the player. For instance, if you have coins in your game, you need to store the count of collected coins somehow to show the coins whenever the player plays the game.

First, you need to decide what data you will be storing. For the sake of demonstration, I will be storing only the count of coins that the player collects. If you have a quest system in your game, you’d need to store more than that. Jump counts, rolling counts, death counts, levels, missions so forth, and so on.

In your scripts folder create a new folder called GameData.

./Assets/scripts/GameData/

Let’s create our first script.

./Assets/scripts/GameData/GameData.cs
[System.Serializable]
public class GameData
{
public int coins;
//constructor
public GameData(){
coins = 0;
}
}

We should remove the MonoBehavior extension because we won’t be creating any object with this class. We will be only using it to store the data. We have to add ‘[System.Serializable]’ to head of GameData class, otherwise, it won’t let us store the data. It basically makes the class ‘savable’.

In the constructor, we initialize the variables by 0 or whatever you want.

Let’s move on to the next script. Just read the comments and copy the script.

./Assets/scripts/GameData/GameDataController.cs
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class GameDataController
{
// We create a static function, so that we can call the function without creating an object of GameDataController
public static void SaveData(GameData data)
{
// To store data securely, we need to convert GameData object to binary by using 'BinaryFormetter'.
BinaryFormatter formatter = new BinaryFormatter();
//The path you will be storing data, does not matter what you wrote in the quotes but I like writing some funny texts. // One thing you need to consider is that the part youcanwritewhateveryouwanttohere is the name of file and the part alsohere is the extension of the file. Don't forget to put a dot beetween them.
string path = Application.persistentDataPath+ "/youcanwritewhateveryouwanttohere.alsohere" ;
FileStream stream = new FileStream(path, FileMode.Create);
formatter.Serialize(stream, data);
stream.Close();
}
public static GameData LoadData()
{
// The path you will be reading the data from. The name of the file have to be same with the file name that you saved in SaveData function. I recommend you to create a constant value that stores the file name to prevent confusions.
string path = Application.persistentDataPath + "/youcanwritewhateveryouwanttohere.alsohere";
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
GameData data = formatter.Deserialize(stream) as GameData;
stream.Close();
return data;
}
else
{
// This part is optional but it basically ensures that no error will be given.
GameData data = new GameData();
SaveData(data);
return data;
}
}
}

Don’t dive into too much how this script works. This script will be a script that you will copy from project to project, and each time it will work just fine.

Here it comes the best part.

Think of that you added a quest your game that says collect 1000 coins. Do you think is it logical to collect 1000 coins to see what the outcome will be, or scripts will work just fine?

Of course not.

To prevent this we will have a class that we can manage our data.

./Assets/scripts/GameData/GameDataInitiator.csusing System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameDataInitiator : MonoBehaviour
{
[SerializeField] private bool loadData;
[SerializeField] private GameData gameData;
[SerializeField] private bool saveData;
private void Start()
{
saveData = false;
gameData = GameDataController.LoadData();
loadData = false;
}
private void Update()
{
if (saveData)
{
GameDataController.SaveData(gameData);
saveData = false;
}
if(loadData)
{
questsData = GameDataController.LoadData();
loadData = false;
}
}
}

Create an object in your scene called GameDataInitiator and link the above class to the object you’ve just created.

Since GameData class is a Serializable class you can edit the data on the inspector.

Let’s say you have a quest that asks to collect 1000 coins. To see if the pop-up you’ve created shows up when the quest is done, we need to set the count of collected coins to lower than 1000, let it be 995.

Start game. Click the GameDataInitiator object you’ve created. Change the coin count 0 to 995 in inspector and click the save boolean. Otherwise it won’t be saved. You won’t see the save boolean stays true because it will be immediately equalized to false because of Update().

Now you can collect 5 coins to see if the pop-up works.

Thanks for reading.

If that does not work, reach me out.

--

--