0

what is best practice so save game progress for a simple 2D game? With "progress" I mean really simple values like "number of collected items" (int), "highscore" (int), "amount of currency" (float) and "is avatar unlocked" (bool). There is no worldmap state or anything big to be saved. I used playerprefs but this is designed for preferences and should be avoided according to many experts. That's why I want to change this now.

I read this thread: Stackoverflow Question, but I cannot identify the best solution for my case as there is no comparison of the proposed methods.

My requirements are simply:

  • applicable for iOS and Android
  • not being deleted when a new Version of the App is published
  • easy to use in the script as we refer at many points to the variables

Any suggestions?

afot2020
  • 11
  • 1
  • 6

1 Answers1

1

Personnaly, I like to write directly into a file. It's applicable to all platforms, isn't removed on an app update, and you have full control over the way you access the data. It's easy to add, remove, edit the contents, and easy to handle multiple save states.

You can do it with a simple class, such as this one :

public static class FileUtils
{
    public static void WriteToFile(string fileName, string json)
    {
        var path = GetFilePath(fileName);
        var stream = new FileStream(path, FileMode.Create);

        using (var writer = new StreamWriter(stream))
            writer.Write(json);
    }

    public static string ReadFromFile(string fileName)
    {
        var path = GetFilePath(fileName);
        if (File.Exists(path))
        {
            using (var reader = new StreamReader(path))
                return reader.ReadToEnd();
        }

        Debug.LogWarning($"{fileName} not found.");
        return null;
    }

    public static string GetFilePath(string fileName)
    {
        return Path.Combine(Application.persistentDataPath, fileName);
    }
}

And then, you just need a Serializable class or struct to save, here I use JSON :

    [Serializable]
    public class UserData
    {
        public string userName;
        public string profilePictureRef;

        public UserData(string userName, string profilePictureRef)
        {
            this.userName = userName;
            this.profilePictureRef = profilePictureRef;
        }
    }

    public void SaveUserData(UserData data)
    {
        var jsonData = JsonUtility.ToJson(data);
        FileUtils.WriteToFile(_fileName, jsonData);
    }

    public void LoadUserData()
    {
        var jsonData = FileUtils.ReadFromFile(_fileName);
        _data = JsonUtility.FromJson<UserData>(jsonData);
    }

You can even fetch some JSON from a server and save it locally. Maybe you'll want to "blur" the contents so that the player can't edit them by hand.

Stev
  • 161
  • 3
  • Thank you! So the solution would be a binary file in combination with JSON, right? How do I "blur" the contents? – afot2020 Jul 25 '20 at 06:13
  • Yep ! Note that you can use whatever format you want as long as you can parse it (XML, CSV, ...), but it's so easy to parse JSON in Unity. For the encryption part (the "blur"), it's up to you. Note that it's really complicated to have something strong and bullet proof. In most cases it's useless, if the player want to cheat to have a fake highscore at 9999 in a solo game ? Not worst the hassle. If you really need to, you can use encryption such as AES, XOR encryption, or even some homebrew methods. Problem is that the key used to decypher will be stored in your compiled assemblies... – Stev Jul 25 '20 at 10:51