Regarding saving player data, there are multiple options available in Unity. Data can be saved in Unity's PlayerPrefs, saved in a file, or even uploaded to a server. This data does not need to exist between game sessions.

The scale of saved data may vary from simple user preferences such as volume, player's name, and player's level to more complex data such as saving the world's state in an open world game, actions performed by AI in-game, game's state in the board, card values, object's position in the world, etc. Depending on the data's complexity and the game's platform, you may want to decide which saving system to use.

Saving Using PlayerPrefs

PlayerPrefs is a simple saving system provided by Unity. It can be used to save strings, floats and integer data types. Data is stored as key-value pair. Saving and loading integer values is as simple as PlayerPrefs.SetInt(Key,int-value) and PlayerPrefs.GetInt(Key) .

For example, we want to save and load the player's Name and Level. This can be done simply as,

// save
PlayerPrefs.SetString("Name", "apple");
PlayerPrefs.SetInt("Level", 4);

//load
Debug.Log(PlayerPrefs.LoadString("Name")); // apple
Debug.Log(PlayerPrefs.LoadInt("Level")); // 4
Saving and Loading in PlayerPrefs

Drawbacks of PlayerPrefs

Considering how simple it is to save data using PlayerPrefs, why not save everything with it? There are some issues with it. Let's discuss them.

The first reason is the place where it stores data. PlayerPrefs on a Windows device are saved in the registry, which can be a huge problem if not managed properly. The registry is built to save small application configurations, so saving large data might cause problems. Saving a large amount of data in a window registry can also corrupt it.

Another issue that we may encounter is due to the way it saves data. Since PlayerPrefs uses key-value pairs, extracting data is troublesome. It is impossible to extract as a whole, so we need to extract each data individually.

PlayerPrefs is also not versatile as a value needs a unique key to save. In the example above, we saved 2 variables. It required 2 separate keys. Imagine saving and loading 10 other variables. You need to have 10 separate keys and manage them. You can already see an increase in complexity as the size of data increases.

The location and format of saved data are also not under the developer's control. The saved data path and format are predefined by Unity. This is also different from platform to platform, so it might be another issue.

When to use PlayerPrefs?

Despite having drawbacks, PlayerPrefs can have uses in saving simple data. It can store volume, sound on/off, screen resolutions etc.

It is also simple and beginner-friendly, so new users can use it easily. It provides enough functionality for starters.

Now we know about the drawbacks of PlayerPrefs, what are its alternatives?

Saving Using File System

In this method, data will be saved in a text file. Data will be converted into JSON strings and will be saved as text. While loading, we load this string from the saved file and convert it back to an object. This file can be saved in any path, but it is recommended to save it in Application.persistientDataPath  or Application.dataPath .

Let's look at an example of how it can be done.

Steps for Saving Data in File System

First, we need to create a class to define the data we are saving. Create a simple class with integer Name and string Level in it.

class SaveData {
  public string name;
  public int level;
}
Class for Save Data

Now create an object saveData with data to be saved.

SaveData saveData = new SaveData() {name= "apple", level= 5};

Next, we need to Serialize it into JSON using JsonUtility.

string saveDataString = JsonUtility.ToJson(saveData);

We will also require a path for data to be saved. For this, let's use a persistent data path.

string savePath = Application.persistentDataPath + "saveData.json";

Now we can save data saveDataString to savePath as,

using StreamWriter streamWriter = new StreamWriter(savePath);
streamWriter.Write(saveDataString);
Saving Data to File

You can load the saved string as,

using StreamReader streamReader = new StreamReader(savePath);
string savedDataString = streamReader.ReadToEnd();
SaveData savedData = JsonUtility.FromJson < SaveData > (savedDataString);
Reading Data From File

In this way, you can save complex data in a file.

Advantages of File System Over PlayerPrefs

Saving data in a file allows you to save huge complex data in a single file. The data can easily be converted to JSON string and saved. It is especially useful when saving data such as levels, GameObject's information such as position and rotation, etc.

Saving in a File System means data can be separated into multiple files. This allows us to categorize data into different categories. For example, we may want to separate settings data with the player's progress data. Sub-folder can also be created using it. Using it, we can maintain the hierarchy of data.

Alternatively, it also allows for easy data extraction as all the data are stored in a single file, and exporting data is easier. It can be useful when we want to upload saved data to the cloud or transfer saved data to another game instance.

Saved JSON data is easily readable by humans. If we know the file's path, we can find that file and open it with any text editor. We can also modify it if we want.

Conclusion

As we can see, it is preferable to use a file system instead of PlayerPrefs while saving game data. File systems are more versatile and are under the user's control. But this doesn't mean we should avoid using PlayerPrefs altogether.

I recommend using PlayerPrefs for simpler data such as user settings or game configs. These data are not exported and remain in the user's device only. Use file systems for more complex data structures.

Thanks for reading, more posts coming soon. Subcribe so you don't miss them!