Help to find best save system solution please

I was using playerprefs without any problem yet. There is around 30-40 data to save total and most of them is like
Table + ID is active or not or general infos like speed, money…

I was actually happy with playerprefs but its because everyone saying me to changing that is important i started to research new system. Yesterday was full day of researching i know there are similar topics but i couldnt find the best system for myself to use. I watched a lot of tutorials but they looked so confusing to me. The only tutorial i understand was brackeys but people said that is outdated and you should not use that.

I found this free asset its easy to use like playerprefs

Saving example

SaveGame.Save<string> ( "simple.txt", "Simple Data" );

Loading example

string simple = SaveGame.Load<string> ( "simple.txt", "The Default Value" );

But in comments people say when you save like that it saves every variable to diffrent file which is bad for disk space i think.

So my main question can you suggest me unity asset or tutorial video to make save system.

If it can be similar to playerprefs it will be good.
I will use it in both android and ios.

And i see that in some save systems it write to json and then save it as a playerprefs string what is the point of that? I’d rather use playerprefs than do that.

Load/Save steps:

An excellent discussion of loading/saving in Unity3D by Xarbrough:

Loading/Saving ScriptableObjects by a proxy identifier such as name:

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

If you want to use PlayerPrefs to save your game, it’s always better to use a JSON-based wrapper such as this one I forked from a fellow named Brett M Johnson on github:

Do not use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

Json-based wrapper seems like all i need to do referance this script instead of playerprefs and it will auto write that save to json file. But like i asked in the topic what is the point of that? Why i should use it

I’m not really in the business of motivating people to choose one solution or the other. There’s plenty of discussions available about save options online.

This is after all engineering, where every choice is possible and potentially correct, and each approach has tradeoffs.

You are welcome to choose either solution, based on your appreciation of all input above.

Sorry i didnt mean that i look for motivation. I mean was if we use this instead of playerprefs what will be the diffrent. The main problem in playerprefs is that i hear player can change the data easly and its getting massy when saving a lot of data. But if we use this script it will be same amount code and json file is also easly changable am i wrong?

I liked that solution from the others you send me looks more easy thats why asking

THe main difference on a Windows desktop is that playerprefs writes to system registry instead of a file.

See here for the full list of where playerprefs are stored based on platform:
https://docs.unity3d.com/2020.1/Documentation/ScriptReference/PlayerPrefs.html

1 Like

I like easy, easy is good. As the docs call out, PlayerPrefs is for “preferences,” which doesn’t mean “save a Skyrim game.”

If you have it working, move on. If it fails for you in the future, revisit it and see why, and adjust accordingly.

1 Like

I understand if i use json+playerprefs mix instead of playerprefs i will be able to change save file directory. Which is not important for my game currently.

I will do like that then i think.

Thank you very much for both answers.

1 Like

Making a save file is easy.

Step 1: you create a json with default values.

{
    name: "Arbator the Bold",
    age: 24,
    items: [11, 24, 48]
}

Step 2: you copy your json in Assets/Resources/Json/Save.json (create the folder if necessary)

Step 3:

in your Awake() function:

    optionsPath = Application.persistentDataPath + "/Options.json";
    if (!File.Exists(optionsPath) {
         var jsonFile =  Resources.Load<TextAsset>("Json/Save");
         File.WriteAllText(optionsPath, jsonFile.text);
    }
    // from there your save data is in optionsPath
    var json = File.ReadAllText(optionsPath);
    // deserialize with your favorite method here
1 Like

Unless im misreading that part, you are thinking about how easily players might cheat given one method of saving versus another? Stop. Dont do that. It’s a huge waste of time to consider, and usually only leads to problems for anybody but the cheaters. People who want to cheat, will do so. The difference in effort between directly editing a savegame and finding a tool to help you cheat is negligible. Yet some developers go out of their way to try and stop people from cheating in singleplayers games. That’s simply a futile effort. Their system, their code copy, they can do whatever they want, and there is literally nothing you can do to stop them, unless you are going to involve a server. Some successful games, like Hades, even embraced the idea that some players might want to cheat and add the option to do so freely, which gives them control over how people cheat, in order to keep a similar game experience.

Even in (mobile) games where you may lose out on microtransactions due to some people cheating, it’s usually not a practical idea to address this. Again, you cannot prevent them fully, unless you involve a server. But attempting to make it harder will cost a lot of your time and attention, which you may otherwise focus on making the game actually good, thus attracting more players.

2 Likes

Yes i agree i dont mind if players want to cheat. I was just trying to find why i should not use playerprefs and it was one of the reasons.

The reasons why playerprefs are not really suited for save games have already been mentioned. Though let be summarize:

  • PlayerPrefs are meant to store preferences for the Unity player. So only to store simply key-value pairs without any structure
  • PlayerPrefs are stored quite different on different platforms. On Windows they are stored in the windows registry. So storing huge information there is not a good idea.
  • Storing complex information in playerprefs is not really portable. So it would be difficult to export or transfer data stored in playerprefs.
  • PlayerPrefs do not have any means to list the stored preferences. So you can not simply iterate through them. This complicates managing several savegames.
  • When using JSON you can store arbitrarily complex information as a single string. That string could even be stored in a single PlayerPrefs string value, though because of the above mentioned points this is not really recommended.
  • Having savegames as JSON makes it much easier to transfer, backup and manage them. You’re free to store them all in one file, each save in a separate file or whatever underlying storage system you want to use. Sending / loading it from a server, in a database or a file works equally well with almost no modification. So the actual serialization of the savegame data would always be the same
2 Likes
string defaultSavePath = "Assets/Json/Save.json";

It might work better if you load it from resources, assets are not always copied in build.

2 Likes

Actually they are never copied verbatim with the only exception of the StreamingAssets folder. Though even that has special cases on Android as those are still packed into the APK file and not actual files. Save files are usually stored in the persistentDataPath. This is the designated place to store data that should persist. This should even work in webgl builds where it uses the IndexedDB to emulate a file system.

1 Like

Yes it’s a design flaw on my side because it works in the editor then when you build in Windows it still works because the file has been initialized. It’s only on a fresh install that the issue arises.

1 Like