Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

HELP Binary save system

Discussion in 'Scripting' started by SonGokuBg, May 7, 2020.

  1. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    But currently all variables are saving to "/Save/saved.coins"?
     
  2. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    yes, you can change the paths and file name if you want
     
  3. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
  4. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
  5. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    then how to change the material from ''shop'' to 15 levels ..
    Thanks for the answer .
     
  6. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    maybe try without prefab and use normal material on mesh renderer
     
  7. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    What you mean without prefab? How I will assign the "player" GameObject from the "Shop" scene to each level scene?
     
  8. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    The save system doesn't work when I build the game :(
     
  9. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    this is really bad
     
  10. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I really don't want to be annoying, but I really need that save system to work
     
  11. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    no problem my friend, now you can change to persistentdatapath, and it should work now.

    make sure you know which folder the persistentdatapath leads you to so you can upkeep your files there

    or you can also set one folder on your desktop as path that also works

    you can also leave it all as it is and copy the save folder to your build_datafolder ( this one works with applicationdatapath)
     
  12. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    But if you remember when I change it I get this errors
     
  13. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    You should definitely take a step back and get a more solid understanding of the language's fundamentals.

    Or read the error messages and try to solve the errors on your own / by googling, OR if you really can't find a solution, make ONE post, include all necessary information.. The way you're trying to finish the save system by always saying "it doesn't work, please fix it" won't help you at all, nor is it enough information for anyone here to know what's going on in your application.
    This is not meant to be rude, but there needs to be more effort on your side.
     
  14. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I forgot the screenshot
     

    Attached Files:

  15. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I am trying like 1 month already
     
  16. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Do not post screens, just post error messages using code tags or a quote.

    On top it says there's an exception because it's unable to load a type that is required for deserialization.

    Also, the screenshot says you're having sharing violations. You're most-likely not disposing the streams correctly, which is the case when I look at the code that's been posted here.
    The code that you're using for reading and writing has the potential to keep the files opened when errors occur. Subsequent operations will fail, because the file is "still in use", so to say.

    With that in mind, the exception on top may be the reason for the subsequent exceptions (the sharing violations), as it fails during reading, files stay "in use" and the following load/save operations attempt to operate on that very same file.

    I'm not entirely sure what you're trying to deserialize there. Note that binary save files are often incompatible when you changed the data type that you serialize/deserialize. Reading the posts here it seems you're continuously trying to add new information to the type that's meant to be laoded/saved.

    This won't be an easy thing with binary save/load systems.
    Suppose you save data type version 1 which has 2 floats.
    Now you decide to add a string and a bool. That's not guaranteed to work with the binary formatter, as it includes type and data size information.

    In early development, you'll just want to delete the old save data manually and use the most-recent version .
    Once a version of your application is released, this will be a lot trickier, because you need trial+error in order to support backwards compatibility.
    In practice, that'd work something like:
    - attempt to read using the most recent data type version
    - if it failed, use the previous version
    - if it failed, use the previous version
    ...
    - when it succeeded, "update" the saved data using the latest data type version.

    But we're drifting away from the actual basic problem here.

    For now, delete any save-file. Run your program, see what happens. Post the exceptions. Then start to fix the issues one by one, starting with the first issue that occurs.

    As for stream+serialization, I've posted a quick (but incomplete) wrapper here. Do not post in that thread though, as it's not your topic and everything has been resolved there.
    The implementation I've linked shows the basic pattern of how streams (which must be disposed) can be easily used with language feature such as the 'using'-statement, which will guarantee disposal no matter what happens (this will most-likely solve your sharing violations which were revealed by the exception that occurred before).

    As for the other error about your data type not being deserializable, you need to post more information including the code you've used.
     
    Last edited: May 21, 2020
  17. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    Finally!!!! I deleted the old files from %AppData%/etc. (the path from the error )
     
  18. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    good! now remember everytime you add new things to the save class you need to go to that directory to delete that file.
     
    Suddoha likes this.
  19. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    @Suddoha could I ask you the proper implementation for this wrapper incase I am using a permanent filestream var to avoid garbage collection?

    Code (CSharp):
    1. public BinaryFormatter bf = new BinaryFormatter();
    2. public FileStream fs;
    3.  
    4. public void serializeData(){
    5.  
    6. using (fs = File.Create(filepath) )
    7.         {
    8.             bf.Serialize(fs, savedata);
    9.         }
    10. }
    11.  
    Is this valid syntax, or valid overall, what happens when the public filestream is disposed, does it become unusable, etc? Thanks!
     
  20. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Syntactically this is fine, but storing the stream in a field doesn't make sense in this particular case, because
    1) you re-create it every time you call SerializeData
    2) the 'using'-statement ensures the stream will be disposed when leaving that block, that's what it exists for in this context.

    So you'd have a disposed stream object hanging around until it's replaced by another (when SerializeData is called again) which will also be disposed when the using-block is left.

    There are scenarios in which you wanna keep a stream open for a longer period of time, e.g. networking streams, or streams for buffering data because it'd otherwise be too much to read or write with a single operation.
    In these cases 'using' won't be helpful, you'll then need to handle everything on your own.

    Most of the time though, for instance when saving some game data, you want to open the stream only when you need it. E.g. get all the data you wanna save first, then open the stream, write your data, dispose/close it. Do not open it when there's lots of other stuff to be done before you write data. As a general rule: the duration of open streams should generally be as short as possible unless there is an actual need to keep it open much longer.
     
    brigas likes this.
  21. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    Hello,
    I am using
    Code (CSharp):
    1. transform.SetParent
    to change the parent/position of a GameObject, but when I restart the game it goes back to its old position. Do I need to use a whole save system for that? This is for inventory purposes.
     
  22. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    everything you change during runtime will reset if you dont save and load
     
  23. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    Uh, how I will save so many things
     
  24. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
  25. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    you will have to write the code for each one
     
  26. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    i need to save vector 3?
     
  27. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    yes, but vector3 cant be serialized so you need take the x y z from the vector 3 and save that

    float x, float y, float z, and then use it to create a vector 3 when you load
     
  28. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    there must be another way I can't do that for 50 items
     
  29. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    you can use a loop to do it
     
  30. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I feel like you are trying to give me a hint, but I not sure it it's possible in my case
     
  31. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    you can loop through all your objects and make a list of their position.

    Then when you load you set them on that position
     
  32. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I am stupid.. I can't image how to do that
     
  33. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    Btw do you know why this doesn't work in the Awake/Start method, but it does work in the Update method?
    Code (CSharp):
    1.  public string currentMaterial;
    2.  
    3.     public GameObject player;
    4.     public Material[] materials;
    5.  
    6.     void Awake ()
    7.     {
    8.         currentMaterial = saveSystem.CurrentMaterial;
    9.         switch (currentMaterial)
    10.         {
    11.             case "DefaultWhite":
    12.                 player.GetComponent<MeshRenderer>().material = materials[0];
    13.                 break;
    14.             case "Red":
    15.                 player.GetComponent<MeshRenderer>().material = materials[1];
    16.                 break;
    17.             case "Blue":
    18.                 player.GetComponent<MeshRenderer>().material = materials[2];
    19.                 break;
    20.             case "Green":
    21.                 player.GetComponent<MeshRenderer>().material = materials[3];
    22.                 break;
    23.             case "Pink":
    24.                 player.GetComponent<MeshRenderer>().material = materials[4];
    25.                 break;
    26.             case "Yellow":
    27.                 player.GetComponent<MeshRenderer>().material = materials[5];
    28.                 break;
    29.             case "Black":
    30.                 player.GetComponent<MeshRenderer>().material = materials[6];
    31.                 break;
    32.         }
    33.     }
    CurrentMaterial is set before the game start
     
  34. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    probably because here

    Code (CSharp):
    1.  currentMaterial = saveSystem.CurrentMaterial;
    when you check this in awake saveSystem.CurrentMaterial is probably not set.

    you can easy check this by adding:

    Code (CSharp):
    1.  currentMaterial = saveSystem.CurrentMaterial;
    2. Debug.Log(currentMaterial );
    this debug log will tell you what is going wrong
     
  35. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I am even setting it in the inspector before start
     
  36. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    looks like this doesn't work
    Code (CSharp):
    1.     currentMaterial = saveSystem.CurrentMaterial;
     
  37. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    well maybe your save system is loading something diferent than what you have in inspector
     
  38. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I fixed it! The problem was that when I use TriggerLoad it's triggering 1 frame after currentMaterial = saveSystem.CurrentMaterial
     
  39. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    yes like i told you triggerload only works on update so you should change to just load()
     
  40. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    we can get back to the other question :D
     
  41. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    can you give me an example ?
     
  42. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    dont know what you want to do
     
  43. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I want to move an object via transform.SetParent and I want to save that
     
  44. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    put your objects in an array of gameobjects.

    Code (CSharp):
    1. public GameObject[ ] objArray;
    then in each object add an id


    Code (CSharp):
    1. public class objectIdentif : MonoBehaviour{
    2.  
    3. public int obj_ID;
    4.  
    5. }
    you must set this id in inspector and it must be the same as the element in the obj array

    for example your parent is ID = 0, your child is ID =1;

    it means that you must drag them to objarray element 0 and element 1

    then add this to your save data
    Code (CSharp):
    1. public list<int>[ ] objChildren;
    and when you save

    Code (CSharp):
    1.  
    2. objChildren = new list<int>[ objArray.length ];
    3.  
    4. for( int i = 0; i< objArray.Length; i++){
    5.  
    6. for( int j = 0; j < objArray[i].transform.childcount; i++){
    7.  
    8. objChildren[i].add(objArray[i].transform.getchild(j).getcomponent<objectIdentif>().obj_ID);
    9.  
    10. }
    11.  
    12. }

    and to load
    Code (CSharp):
    1.  
    2.  
    3. for( int i = 0; i < objChildren.length; i++){
    4.  
    5. for( int j =0 ; j < objChildren[j].count; j++){
    6.  
    7. objArray[j].transform.setparent(objArray[i]);
    8. }
    9.  
    10. }
    11.  
    12.  
     
    Last edited: May 29, 2020
  45. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    It's even more complicated because I only want to do transform.setparent for the objects that are bought
     
  46. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    I watched so many videos and my F***ing brain still can't figure it out
     
  47. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    upload_2020-5-29_17-4-48.png
    I don't understand that
     
  48. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    it means that you need to add something to identify each object so you can look it up on an array.

    you are doing the same with your materials

    imagine that instead of "defaultwhite", you just called it colorID = 0;

    then you could do materialarray[colorID], instead of if "defaultWhite" then material[0]
     
  49. SonGokuBg

    SonGokuBg

    Joined:
    Apr 16, 2020
    Posts:
    146
    That means I need to make multiple of this variable ?
    Code (CSharp):
    1. public int obj_ID;
     
  50. brigas

    brigas

    Joined:
    Oct 4, 2014
    Posts:
    522
    yes all your objects that you want to save need to have that variable.

    then each object needs to have a different number

    object0 > obj_ID = 0
    object1 > obj_ID = 1

    and then all your objects need to be in an array, and you must put them in the correct order
    so that when you write

    objArray[ obj_ID] you get a reference to the object which has that ID

    this is so you can access all your objects that you need to save and load