Unity Basics Course: Save and Load Functionality, Data Storage

Data storage and retrieval are essential functions in game development. To effectively manage player progress, settings, and the state of the game, Unity offers several data storage methods. In this tutorial, we will explore various ways to store and retrieve data in Unity.

1. The Need for Data Storage

Data storage in games and software applications is important for various reasons:

  • Improved User Experience: Players need a saving function to avoid losing progress in the game.
  • Maintain Settings: Saving user settings (e.g., graphic quality, sound settings, etc.) provides a consistent experience upon restart.
  • Game State Management: Storing various game states (e.g., levels, scores, bonuses, etc.) helps control the flow of the game.

2. Basic Concepts of Data Storage in Unity

Unity offers multiple ways to store data. Common methods include PlayerPrefs, JSON files, binary files, and XML files.

3. Data Storage Using PlayerPrefs

PlayerPrefs provides a very convenient way to store simple data (strings, integers, floats). It allows easy saving of player scores, game settings, and more. The example below demonstrates how to save and retrieve scores using PlayerPrefs.


using UnityEngine;

public class PlayerScore : MonoBehaviour
{
    private int score = 0;

    void Start()
    {
        // Retrieving the saved score
        score = PlayerPrefs.GetInt("PlayerScore", 0);
        Debug.Log("Saved Score: " + score);
    }

    public void SaveScore(int newScore)
    {
        score = newScore;
        PlayerPrefs.SetInt("PlayerScore", score);
        PlayerPrefs.Save(); // Save changes
        Debug.Log("Score Saved: " + score);
    }
}

In the code above, PlayerPrefs.GetInt is the method for retrieving the saved score, while PlayerPrefs.SetInt is the method for storing the score.

4. Data Storage Using JSON

JSON (JavaScript Object Notation) is a suitable format for serializing and storing data. Unity allows converting classes to JSON format using JSONUtility. The example below shows the process of saving and loading player information in a JSON file.


[System.Serializable]
public class PlayerData
{
    public string playerName;
    public int playerScore;
}

using UnityEngine;
using System.IO;

public class JsonManager : MonoBehaviour
{
    private string filePath;

    void Start()
    {
        filePath = Path.Combine(Application.persistentDataPath, "playerData.json");
        LoadPlayerData();
    }

    public void SavePlayerData(PlayerData data)
    {
        string json = JsonUtility.ToJson(data);
        File.WriteAllText(filePath, json);
        Debug.Log("Player Data Saved.");
    }

    public void LoadPlayerData()
    {
        if (File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            PlayerData data = JsonUtility.FromJson(json);
            Debug.Log("Player Name: " + data.playerName);
            Debug.Log("Player Score: " + data.playerScore);
        }
        else
        {
            Debug.Log("No saved file found.");
        }
    }
}

5. Data Storage Using Binary Files

Binary files can store data in a more compact form and are advantageous for large-scale data storage. Below is an implementation example of saving and loading data using binary files.


using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

[Serializable]
public class PlayerStats
{
    public string playerName;
    public int playerLevel;
}

public class BinaryManager : MonoBehaviour
{
    private string filePath;

    void Start()
    {
        filePath = Path.Combine(Application.persistentDataPath, "playerStats.dat");
        LoadPlayerStats();
    }

    public void SavePlayerStats(PlayerStats stats)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        FileStream stream = new FileStream(filePath, FileMode.Create);

        formatter.Serialize(stream, stats);
        stream.Close();
        Debug.Log("Player Stats Saved.");
    }

    public void LoadPlayerStats()
    {
        if (File.Exists(filePath))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(filePath, FileMode.Open);

            PlayerStats stats = formatter.Deserialize(stream) as PlayerStats;
            stream.Close();

            Debug.Log("Player Name: " + stats.playerName);
            Debug.Log("Player Level: " + stats.playerLevel);
        }
        else
        {
            Debug.Log("No saved file found.");
        }
    }
}

6. Data Storage Using XML Files

XML is another method for storing structured data. XML files are human-readable and supported across various platforms. Below is an example of saving and loading using XML files.


using System.Xml.Serialization;
using System.IO;

public class XmlManager : MonoBehaviour
{
    private string filePath;

    void Start()
    {
        filePath = Path.Combine(Application.persistentDataPath, "playerInfo.xml");
        LoadPlayerInfo();
    }

    public void SavePlayerInfo(PlayerData data)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
        FileStream stream = new FileStream(filePath, FileMode.Create);
        
        serializer.Serialize(stream, data);
        stream.Close();
        Debug.Log("Player Info Saved.");
    }

    public void LoadPlayerInfo()
    {
        if (File.Exists(filePath))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
            FileStream stream = new FileStream(filePath, FileMode.Open);
            
            PlayerData data = serializer.Deserialize(stream) as PlayerData;
            stream.Close();

            Debug.Log("Player Name: " + data.playerName);
            Debug.Log("Player Score: " + data.playerScore);
        }
        else
        {
            Debug.Log("No saved file found.");
        }
    }
}

7. Tips to Enhance the Experience of Data Storage and Retrieval

  • Error Handling: Implement logic to handle potential errors that may occur during data storage and retrieval processes.
  • Support for Various Formats: It is advisable to offer multiple storage formats based on the requirements of a specific game.
  • Performance Optimization: When storing large amounts of data, choose optimized methods considering performance.

8. Conclusion

In this tutorial, we explored the features of saving and loading data in Unity. Various methods such as PlayerPrefs, JSON, binary, and XML allow you to store and retrieve data. This can provide a better experience for users and improve the overall quality of the game.

I hope you understand the importance of data management in various aspects of game development. Keep practicing and try applying these methods in different scenarios. It will be a great help in your future Unity development journey!