Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question What's the best way to build Stats system and Save/Load your Stats?

Discussion in 'Scripting' started by PerfectHiT, Sep 7, 2023.

  1. PerfectHiT

    PerfectHiT

    Joined:
    Feb 16, 2018
    Posts:
    6

    Hello Everyone

    I'm building an ARPG game which has a combat system and i was wondering about the best way to approach the subject and build a solid clean Stats system that stores some of my data a database of some sort.

    Keep in mind the following:-

    1. Some values of the stats system will not migrate with the player, if the player dies they are gone.
    2. Some values will be Base Stats that the player will always start with at the start of the game.
    3. Some values in the data base will be modified by the player so the dataBase isn't fully static.
    4. Some values will be affected by Modifiers (+damage, +health, +armor ..etc) from Many resources.

    Here is a simple chart to make things a bit more clearer:-



    https://imgur.com/a/eHMn4Ut


    Let me give you a scenario of how i think this is going to work"-

    1. The Player will Have unspent talent points that he earned from the previous instance and will Spend them. The Base Stats layer will be updated and now the Player have PERMANENT 110 HP, Armor or Damage that will be saved and loaded in every instance they start.

    2. The Player will Start a new Instance and the Base Stats Laywe will feed The Player their Base Stats at level 1.

    3. While the Player is Progressing through the Instance he will Collect items with Stats and these Items will Also feed the Player Extra Stats that he will lose when the instance is finished or they died.

    4. The Player will Have Abilities that he could use and each Ability have a fixed Damage. If the Player Pressed Q then they will do damage to enemy Equals to Ability DMG + Player DMG.


    My game will be a small one and i don't need a much Complicated Mechanics and attributes like Crit, Hase, Overpowered ..etc So correct me if my Logic is invalid and i'd be more than happy to hear suggestions from you to build a better Logic for my game.

    The second part of the topic is which system should i follow to build to be able to borrow Stats from Scripts and Save and load my Stats System in the game. I've watched ton of videos and did read many articles and these are the following systems are used the most. please keep in mind that im dumb and i might have missed something :-

    1. Playerprefs: highly unrecommended for for many reason such as the data being saved in the registery and will be lost and the build in functionality is not meant for more than saving simple elements of the game such as UI elements and such.

    2. JSON: Your data will be visable to eveyone and will be easily modified which will break the game.

    3. Binary Serialization: Security Risks, Heavy on the machine and highly not recommended.

    4. Scriptable Objects: Static Values are a very bad idea for my kind of game since Itemization system will always have random values and my Base Stats layer need to be Constantly updated.

    5. SQL Database: It hurts my heart that i considered this method and spent 90 minutes watching a video that ended up with the guy saying you shouldn't use SQL when you have better options without mentioning them options so i really really don't like the idea of using this method becaue it look way complicated for my think skull.

    I apologize for my childlike english!

    I really need your Help! i cant decide which direction i shoud head to. I'm looking forward to read from you. I'm Willing to learn any method if it is the correct one from the scratch.




     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    This is a non-issue. People are going to modify game files whether you secure them or not.

    In any case the method of serialisation is secondary to how you actually manage your data at in the game itself. This will take place over multiple layers throughout multiple objects and systems. Such as having scriptable objects for immutable values, and intermediary plain C# objects to manage transient or mutable values.

    And all this should of course be separate to the actual presentation layer.

    The answers to your questions will come from actually working on the project rather than getting stuck in analysis land.
     
    PerfectHiT, CodeSmile and Kurt-Dekker like this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    BAM BAM BAM... BAM!

    You read my mind Spiney.

    Some more stuff to get OP writing code TODAY, which will be the first step to doing ANY savegame system.

    Load/Save steps:

    https://forum.unity.com/threads/save-system-questions.930366/#post-6087384

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

    https://forum.unity.com/threads/save-system.1232301/#post-7872586

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

    https://forum.unity.com/threads/use...lds-in-editor-and-build.1327059/#post-8394573

    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<T>() on a GameObject instance, or use ScriptableObject.CreateInstance<T>() 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:

    https://gist.github.com/kurtdekker/7db0500da01c3eb2a7ac8040198ce7f6

    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.

    https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide
     
    PerfectHiT likes this.
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,191
    That's just bollocks.

    Binary is the most optimized way to save any data, you cannot make data any more machine-friendly than by using the "native" format.

    Reading json or any text-based format is more "heavy on the machine" as it requires reading variable-length chunks of strings, deciding when that string ends (check for delimiters, special cases for delimiters within string data), following the syntax of the format (be it json or yaml or xml or ..) and throwing helpful error messages when the syntax is non-conforming, then converting string attributes into actual values or resolving references by path or GUID and what not.

    Json is also less "secure" as you said because anyone with a text editor can edit it, whereas binary at least requires one to use a hex editor.

    Security of data lies entirely in encryption. But since your app runs on the local machine, encrypting the savegame data is pretty pointless since one can hack into the save routine and get that data out and back in before respectively after the en-/decryption takes place. It will prevent the random user poking around however.

    The biggest issue with binary is that it makes it harder to debug any issues during development. However, even that is totally manageable by writing rigorous unit tests for all save/load code scenarios, and considering versioning which is necessary when one either adds, removes, or changes the type of a serialized value in the data stream.

    If you need to support older versions of the data format, writing loading code that takes into account previous data versions is also a manageable challenge, but one where you need to put serious thought into it because getting that part wrong (eg code duplication, or littering the code with "if (version != 17) .." can make the difference between having next to zero issues with this, or frequently having serious issues with it. Mostly because any errors in reading the data only tend to appear far later (typical errors: "unexpected end of file" and nonsensical values everywhere) than the actual value that was misinterpreted, skipped, or read ahead.
     
    PerfectHiT likes this.
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    I think they mean the Binary Formatter, which by all accounts should not be used in any way shape or form these days.
     
    PerfectHiT likes this.
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,191
    Right. I've never considered that as an option even before it was considered bad practice. :D

    If I remember correctly it does not support versioned binary streams and is therefore useless for savegames and such. But StreamWriter should be okay. The best option being Unity's binary serializer, this one I've come to love!
     
  7. PerfectHiT

    PerfectHiT

    Joined:
    Feb 16, 2018
    Posts:
    6
    Many thanks for the insight! i'll start scripting right away. could you elaborate on ( And all this should of course be separate to the actual presentation layer ).


    Oh thank you so much for the insight. I believe i stumbled around something like creating and populating Scriptable objects and now you mention it it does make since to use that method! ill look into eveything you have said so i appreciate it.


    Thank you for the insight! i agree with what you are saying. one question though, if you where in my shoes how would you build your stats system?
     
    CodeSmile likes this.
  8. PerfectHiT

    PerfectHiT

    Joined:
    Feb 16, 2018
    Posts:
    6
    I did mean that actually its just my english is poor and words failed me. What would you do if you where in my shoes? how would you start building the system and which methods would you use.
     
  9. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,191
  10. PerfectHiT

    PerfectHiT

    Joined:
    Feb 16, 2018
    Posts:
    6
  11. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,184