Local Data Persistence Strategies in Unity

PlayerPrefs for Lightweight Storage

Unity's built-in key-value store suits preferences and small settings.

// Write values
PlayerPrefs.SetString("Username", activeUser);
PlayerPrefs.SetInt("HighScore", bestScore);
PlayerPrefs.SetFloat("MusicVolume", masterVolume);

// Retrieve values
activeUser = PlayerPrefs.GetString("Username", "Guest");
bestScore = PlayerPrefs.GetInt("HighScore", 0);
masterVolume = PlayerPrefs.GetFloat("MusicVolume", 1.0f);

// Remove specific entry
PlayerPrefs.DeleteKey("HighScore");

// Purge everything
PlayerPrefs.DeleteAll();

// Force immediate disk write
PlayerPrefs.Save();

Binary Serialization with BinaryFormatter

For complex objects, a binary format reduces file size and discourages manual editing. Because BinaryFormatter cannot directly handle Unity value types like Vector3, a serializable DTO bridges the gap.

Define the runtime and data transfer objects:

[System.Serializable]
public class Avatar
{
    public int vitality;
    public int energy;
    public Vector3 worldPos;
}

[System.Serializable]
public class AvatarSnapshot
{
    public int vitality;
    public int energy;
    public float[] coords;

    public AvatarSnapshot(Avatar source)
    {
        vitality = source.vitality;
        energy = source.energy;
        coords = new float[3];
        coords[0] = source.worldPos.x;
        coords[1] = source.worldPos.y;
        coords[2] = source.worldPos.z;
    }
}

Static helper for disk operations:

public static class BinaryDataStore
{
    public static void StoreAvatar(Avatar target)
    {
        var formatter = new BinaryFormatter();
        var destination = Path.Combine(Application.persistentDataPath, "avatar.bin");
        
        using (var fs = new FileStream(destination, FileMode.Create))
        {
            var snapshot = new AvatarSnapshot(target);
            formatter.Serialize(fs, snapshot);
        }
    }

    public static AvatarSnapshot RetrieveAvatar()
    {
        var source = Path.Combine(Application.persistentDataPath, "avatar.bin");
        
        if (!File.Exists(source))
        {
            Debug.LogError($"No saved data at {source}");
            return null;
        }

        var formatter = new BinaryFormatter();
        using (var fs = new FileStream(source, FileMode.Open))
        {
            return formatter.Deserialize(fs) as AvatarSnapshot;
        }
    }
}

JSON Text Serialization via JsonUtility

JSON offers human-readable saves and easy external editing. Unity's JsonUtility handles plain C# objects quick.

[System.Serializable]
public class ShipConfiguration
{
    public int hullIntegrity;
    public float shieldPower;
    public string vesselClass;
}
public static class JsonDataStore
{
    public static void StoreShipState(ShipConfiguration vessel)
    {
        var route = Path.Combine(Application.persistentDataPath, "ship.json");
        var payload = JsonUtility.ToJson(vessel, true);
        File.WriteAllText(route, payload);
    }

    public static ShipConfiguration RestoreShipState()
    {
        var route = Path.Combine(Application.persistentDataPath, "ship.json");
        
        if (!File.Exists(route))
        {
            Debug.LogError($"Missing save file: {route}");
            return null;
        }

        var payload = File.ReadAllText(route);
        return JsonUtility.FromJson<ShipConfiguration>(payload);
    }
}

XML Serialization with XmlSerializer

XML remains useful when schema readability or external tool consumption matters. Insure target classes expose parameterless constructors and public fields.

public class CrewMember
{
    public CrewMember() { }

    public CrewMember(string id, string division)
    {
        codename = id;
        unit = division;
    }

    public string codename;
    public string unit;
}

Read and write operations:

var rosterPath = Path.Combine(Application.persistentDataPath, "crew.xml");
List<CrewMember> roster = null;

// Loading
var xmlConverter = new XmlSerializer(typeof(List<CrewMember>));
using (var reader = new StreamReader(rosterPath))
{
    roster = xmlConverter.Deserialize(reader) as List<CrewMember>;
}

// Saving
using (var writer = new StreamWriter(rosterPath))
{
    xmlConverter.Serialize(writer, roster);
}

Resulting file srtucture:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfCrewMember xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <CrewMember>
    <codename>Viper</codename>
    <unit>Navigation</unit>
  </CrewMember>
  <CrewMember>
    <codename>Rook</codename>
    <unit>Engineering</unit>
  </CrewMember>
</ArrayOfCrewMember>

Tags: unity data persistence serialization PlayerPrefs C#

Posted on Tue, 04 Aug 2026 16:41:53 +0000 by rndilger