Search Unity

Easy Save - The Complete Save & Load Asset for Unity

Discussion in 'Assets and Asset Store' started by joeltebbett, May 28, 2011.

  1. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    Hey, I'll take that offer.. no seriously, I just wanted to say how useful this utility is. I found it no trouble to integrate and am using it from both Javascript and C#.

    I actually use it to maintain persistance in my world so when you come back, your location and all items are saved for you.

    In fact, I save everything twice.. once on the players machine and once on the server through PHP. Both are encrypted.

    When a player loads, it grabs the info locally quickly for the restart.. then, in the background, I run a load from the server.. if the info from the machine does not match the server info, I flag the account for possible tampering and investigation.

    I also have checks in place so that should the server be down (different server from the game itself) that the player can still play and the account is flagged as unchecked and a store of the data taken for the next time theres a check to see what's going on :)

    Regards

    Graham
     
  2. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hiya Matt, and thanks for the praise.
    You can specify custom save directories for PC and Mac by changing the windowsDataPath and osxDataPath static variables. More info on this can be found in this page of the documentation.
     
  3. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Graham, it's great to hear what you have been doing with Easy Save. It's certainly the most innovative way I've seen it used!
     
  4. mbaucco

    mbaucco

    Joined:
    Feb 22, 2008
    Posts:
    21
    I did see that, but I am speaking of aliases for a user's home directory, for instance. I won't know the user's name, so how would I save it to their My Documents folder in Windows, for instance?

    Thanks again,
    Matt
     
  5. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    I believe you could use Environment.GetFolderPath(Environment.SpecialFolder.Personal) to find the My Documents folder. The Environment class is really useful when handling directories, so it's well worth checking out the documentation here.
     
  6. mbaucco

    mbaucco

    Joined:
    Feb 22, 2008
    Posts:
    21
    Thanks again, you guys are the best! :)

    -Matt
     
  7. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    Quick question :)

    If I use the method GetFoldersInFolder(string folder) it returns the folder but also includes the persistantdatapath teminated with a \ .

    Is there a method for stripping the persistant data path and the \ from the result, or even a method that just returns the folder names within the folder specified without the persistentdatapath data?

    Also in the documentation, getFoldersInFolder is not documented.

    Regards

    Graham
     
  8. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi Graham,

    You can get just the folder or filename from the full path using the following function:

    Code (csharp):
    1. private static string getStringAfterSlash(string str)
    2. {
    3.     int start = str.LastIndexOf("/")+1;
    4.     return str.Substring(str.LastIndexOf("/")+1,str.Length-start);
    5. }
    The file and folder functions were meant to get just the file name or folder name, but we forgot to put in the newer code for it ... Doh! Thanks for letting us know about the documentation too; it's greatly appreciated.
     
  9. sleglik

    sleglik

    Joined:
    Jun 29, 2011
    Posts:
    682
    I am sorry but name of your private method is quite wrong. It will return LAST word after slash.

    Better for this is use namespace System.IO :).
     
  10. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi Sleglik,

    When using getFoldersInFolder() and getFilesInFolder(), the filename will always be the last word after the final slash. Both of these functions use System.IO.

    Regards,
    Joel
     
    Last edited: Jul 16, 2011
  11. okimoki

    okimoki

    Joined:
    May 13, 2010
    Posts:
    114
    total non-programer here.. i bought Easy Save to make it easy for me to save some parametrs for an iPad project im working on.. and right away i have a proglem with it.. it is of course the most basic and obvious solution to you, but i cant figure what im doing wrong..
    I put EasySave in Standard Assets..
    Then this:

    var LangSel : String;

    function Start() {
    if(!EasySave.fileExists("langPref.txt")){
    LangSel = "eng";
    EasySave.saveString(LangSel, "langPref.txt");
    }
    }

    I want to make sure the parameter langPref hasn't been set before, so i do IF, then if the text file doesnt exist yet i set the string, and save it..

    but on compile it says:
    Assets/SCRIPTS/MENU/MenuController.js(33,36): BCE0017: The best overload for the method 'EasySave.saveString(String, String, EasySave.Mode)' is not compatible with the argument list '(String, String)'.

    What am i doing wrong??
     
  12. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    In Javascript the 3rd parameter is compulsory. Try using this instead:

    Code (csharp):
    1. EasySave.saveString(LangSel, "langPref.txt", EasySave.Mode.Overwrite);
    If you need any other help, please don't hesitate to ask!

    All the best,
    Joel
     
  13. okimoki

    okimoki

    Joined:
    May 13, 2010
    Posts:
    114
    Thanks Joel! Works!! This is a real TIME SAVER, not just strings and bools and floats saver!!!! :)
    I left a review on the assetstore..
     
  14. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    We've just issued an update which addresses the following:

    1) Default parameters now work in Javascript.
    2) Default parameters have been changed so that they work in MonoDevelop.

    Because we don't use MonoDevelop, we didn't know about this issue until today. We're very surprised nobody else had contacted us about this until now. Does anyone reading this use MonoDevelop?

    Expect this release to go live early next week. As with all of our updates, it's backward compatible with previous versions of Easy Save.
     
  15. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    Good question :) If Unity decided to make MonoDevelop the only solution then I would probably look for another engine or just stay on the last version that didn't enforce it.

    First thing I did in 3.4 was get a decent script editor back, so no, sorry I would never have found the bug :) .

    Regards

    Graham
     
  16. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Unity Web Player support is coming this week (Look out for v1.5). It interoperates with PlayerPrefs so you'll have up to 1mb of storage on Web Player. This means that Easy Save is now fully cross-compatible. Not all of the File and Folder functions work yet, but we're hoping to get them working at a later date (only DeleteFile and FileExists works at the moment).

    @Graham: What script editor do you use? We still use Unitron simply because there's little that can go wrong with it. We spend enough time setting up/fixing Unity and Xcode ... the last thing we need is another piece of software built to fail. MonoDevelop is also the sort of software that has a mind of its own, and tries to guess what you're going to do next. I don't know about anyone else, but I like to feel I'm in control when I'm using software :)

    I can see that Unity has put a lot of effort into it, and it's a smart piece of software, but I just think it falls short of the principles of human computer interaction. Anyway, enough of my rambling!
     
  17. lilymontoute

    lilymontoute

    Joined:
    Feb 8, 2011
    Posts:
    1,179
    Sounds great! Been waiting for this. =)
     
  18. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    LOL decent is in the eye of the beholder, but as a non-programmer, I self learnt over the last 9 months purely in UNiSciTE (or however you capitalise it) firstly in JS and now C#. Wonderful thing this learning process, I certainly wouldn't go back to JS now and have converted all my scripts to C# in my game.

    Having said that, if a real programmer looked at my coding, they would probably die laughing, but for me, UNiSciTE has highlighting of keywords, autocompletion and almost has go to line error finding (working on that bit right now, mostly done) and it's quick and easy to use.

    No matter how good Mono develop is, converting a project and having NO errors and still getting an extra 21 files in the project folder that made no sense and having to wait 5 minutes for it to power up were an instant killer... I don't care how good it is or isn't, first impressions were a bust and will remain that way :)

    Regards

    Graham.

    PS YAYYYYY to the web stuff :)
     
  19. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    The Web Player Support update is now up on the Asset Store. Let us know what you think!
     
  20. angel_m

    angel_m

    Joined:
    Nov 4, 2005
    Posts:
    1,128
    Moria, I agree completelly with you about the script editor. I assume it will be possible to use UniSciTE in the next updates (as an option), because in other case it would be a big mistake...
     
  21. 3Duaun

    3Duaun

    Joined:
    Dec 29, 2009
    Posts:
    600
    thanks for the update @joeltebbett
     
  22. lilymontoute

    lilymontoute

    Joined:
    Feb 8, 2011
    Posts:
    1,179
    Unfortunately, I am getting this issue as well, using bytecode stripping only and no exceptions. Is encryption currently supported for mobile devices?
     
  23. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hiya there,
    Encryption does not work with byte code stripping because one of the things that it strips are the security libraries.
     
  24. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    Greetings :)

    okay a little question.... If I have a file that saves a set of names, and each new player has a name added and the file is appended, then the length of that array will be changing.

    In C#, an array has to be fixed length or else an ArrayList or List needs to be used to read in the file.

    However, reading an array gives a string, which cannot be implicitly converted.

    What method do you recommend fopr reading a variable length array into a list or similar so that it can be processed in C#?

    Regards

    Graham
     
  25. lilymontoute

    lilymontoute

    Joined:
    Feb 8, 2011
    Posts:
    1,179
    Yea, figured this out.

    I didn't get to try it out, but I wonder if you could get around that with explicitly specifying the libraries in a link.xml file (http://unity3d.com/support/documentation/Manual/iphone-playerSizeOptimization.html). I'll test it out sometime, and if I can get it to work I'll post my results here - I'm sure people working with mobile would like to be able to do that.

    Great product by the way! Don't think I could look at PlayerPrefs again, haha.
     
  26. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hiya Graham,

    I'm not sure I fully understand your question, but I will try my best to answer it.

    By array do you mean ArrayList/List? If so, you should implicitly convert it using casting. This page describes how to convert an ArrayList to a C# array using casting. This is basically all you need to know:

    Code (csharp):
    1. string[] array = list.ToArray(typeof(string)) as string[];
    If you're using Javascript arrays, you can use the ToBuiltin() function as described here.

    I certainly hope this answers your question. If not, please do let me know!
     
  27. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    That would be great. I very much look forward to seeing if this works!
     
  28. moria15

    moria15

    Joined:
    Feb 25, 2011
    Posts:
    400
    Hi Joeltebbett, sorry I am confusing you :) I actually meant the other way...

    string[] EasySave.getFoldersInFolder(string folder) is saved as an array.

    In C# I need to know the length of the Array in order to read it into another Array, and if I have been appending items to it, then the length of the Array is unknown. So I need to read the Array into an ArrayList/List, however the ArrayList will not take a string input from the getFoldersinFolders, and I can't get the length of the Array until I have read it in.

    So the question is really, how do I read a variable length Array into an ArrayList in C# to be able to play with it.

    I hope that's clearer.

    I am assuming there is an explicit conversion but it's currently eluding me.

    Regards

    Graham
     
  29. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hiya again Graham,

    You don't need to know the length of the array to read it into another array. For example:

    Code (csharp):
    1.  
    2. string[] myNewArray;
    3. myNewArray = EasySave.getFoldersInFolder(string folder);
    4. int lengthOfArray = myNewArray.Length; // Length of array if you need it.
    5.  
    You shouldn't need to append the results of getFoldersInFolder because this would cause duplicate data. When you call getFoldersInFolder, it doesn't remove the folders when it gets them.

    If you have to read them into an ArrayList (for example, if you wanted to get the folder within a number of different folders), the following should suffice:

    Code (csharp):
    1.  
    2. ArrayList myArrayList = new ArrayList();
    3. myArrayList.AddRange(EasySave.getFoldersInFolder("yourFolder"));
    4. myArrayList.AddRange(EasySave.getFoldersInFolder("anotherFolder"));
    5. myArrayList.AddRange(EasySave.getFoldersInFolder("andAnotherFolder"));
    6.  
    All the best,
    Joel
     
  30. matis1989

    matis1989

    Joined:
    Mar 23, 2011
    Posts:
    162
    Hi all,
    can someone help me with my load code? I have a lot of diferent tilles in my game(tiles are instantiate when player go forward - it is some kind of infinite terrain:)) so I use save function from example resource folder "tutorial" in Easy Save project.
    Now my code is:
    Code (csharp):
    1. private GameObject[] cubes = new GameObject[0];
    2. void Update(){
    3. if(Input.GetKeyDown(KeyCode.F6)){
    4.         cubes = GameObject.FindGameObjectsWithTag("cube_test");
    5.         Transform[] ts = new Transform[cubes.Length];
    6.         string[] names = new string[cubes.Length];
    7.         for(int i=0;i<cubes.Length; i++)
    8.         {
    9.             ts[i] = cubes[i].transform;
    10.             names[i] = cubes[i].name;
    11.         }
    12.         EasySave.save(ts,"transforms.txt");
    13.         EasySave.save(names,"names.txt");
    14.         }
    15.        
    16.         if(Input.GetKeyDown(KeyCode.F7)){
    17. //load code
    18. }
    19. }
    If I understand it right this save names of my game objects with tag cube_test and position of each. Now I need load code but I cant figure it out:(
    Thanks for help.
     
  31. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    431
    @joeltebbett : Bought EasySave yesterday and started to use it very quickly. I like the approach, and particularly the fact that you put so much effort on simplicity and clarity.

    When checking the php functions, I saw that EasySave.uploadFileToWeb() is dedicated to previously-saved files. I might have missed something, but I don't see how to manage this from within the webplayer to send big files to a MySQL database, considering the limited size of the webplayer preferences file.
     
  32. ArenMook

    ArenMook

    Joined:
    Oct 20, 2010
    Posts:
    1,902
    I picked it up about a week ago and the only suggestion I can make for tool is to find a way to save data into one file. Having 10 different data types means 10 different save calls, also implying 10 different files. This can be slow on some devices.
     
  33. matis1989

    matis1989

    Joined:
    Mar 23, 2011
    Posts:
    162
    No one can help me? Hm, as a motivation I can send some little money, if someone is interested for this kind of help send me PM please.
     
  34. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi Yann,

    Thanks for the feedback. I've got the team developing a uploadDirectToWeb() function for you as we speak, which will be included in this week's update. If you need it before the end of the week, please email me on joel@moodkie.com and we will get an updated version to you as soon as it is done.
     
  35. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Thanks for the feedback ArenMook,

    We're actually working on this at the moment, though we cannot yet predict when it's going to be finished.

    The reason we haven't included it from the beginning is that we expected novice Unity users to get errors due to trying to load the wrong type of data in the wrong order. However, we're formatting the file in a way that should be able to detect this, without increasing the file size, memory footprint or processing time. We'll keep you all updated in this thread!
     
  36. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi again Matej,

    I'll get you an example written up tomorrow as I'm out-of-office today. I might get the team to write a function which simplifies this process for you and include it in this week's update.
     
  37. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    431
    @joeltebbet : great, thanks a lot !
     
  38. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi Matej,

    Here's the code which I've come up with. I've left some comments which are worth reading and will hopefully improve the structure of your project somewhat. There will be a function included in this weeks update of Easy Save which makes what you want to do much simpler (which I will explain later in this post). However, here's how you would code what you want without the new update:

    Code (csharp):
    1. /*
    2.     Notes:
    3.     You should have some code which makes sure the user can't load
    4.     the same data many times. I've not included this but it should
    5.     be very easy to implement.
    6. */
    7.  
    8. public GameObject tilePrefab; // Drag your tile prefab here in Unity.
    9. public GameObject[] instantiatedTiles = new GameObject[0];
    10.  
    11. void Update()
    12. {
    13. if(Input.GetKeyDown(KeyCode.F6))
    14. {
    15.    // Better for memory management if array is defined locally
    16.    GameObject[] cubes = new GameObject[0];
    17.    
    18.    // You would be better off instantiating your objects into an array.
    19.    // See my load code below for an example of this.
    20.    cubes = GameObject.FindGameObjectsWithTag("cube_test");
    21.    
    22.    // I've deleted the 'names' array because that's only required
    23.    // if you're dynamically loading from Resources folder.
    24.    Transform[] ts = new Transform[cubes.Length];
    25.    
    26.    for(int i=0;i<cubes.Length; i++)
    27.    {
    28.       ts[i] = cubes[i].transform;
    29.       Destroy(cubes[i]);
    30.    }
    31.    EasySave.save(ts,"transforms.txt");
    32. }      
    33. if(Input.GetKeyDown(KeyCode.F7))
    34. {  
    35.    Transform[] loadedTs = EasySave.loadTransformArray("transforms.txt");
    36.    int numberOfTiles = loadedTs.Length;
    37.    
    38.    instantiatedTiles = new GameObject[numberOfTiles];
    39.    
    40.    for(int i=0;i<numberOfTiles;i++)
    41.    {
    42.       instantiatedTiles[i] = Instantiate(tilePrefab,loadedTs[i].position,loadedTs[i].rotation) as GameObject;
    43.       instantiatedTiles[i].transform.localScale = loadedTs[i].localScale;
    44.    }
    45. }
    46. }
    However, once you install the update which should be coming towards the end of the week, you should be able to replace the final IF statement with this:

    Code (csharp):
    1. if(Input.GetKeyDown(KeyCode.F7))
    2. {  
    3.    instantiatedTiles = EasySave.loadTransformsAndInstantiate("transforms.txt",
    4.                                                                   tilePrefab);
    5. }
    This way will require far less memory and uses fewer cycles too, so I advise using this function when it comes out if you're instantiating transforms which you have loaded from a file. I will be submitting the update to Unity tomorrow, so hopefully it will be here by the end of the week.

    If you need any more help regarding Easy Save, let me know!
     
    Last edited: Oct 25, 2011
  39. matis1989

    matis1989

    Joined:
    Mar 23, 2011
    Posts:
    162
    Hi, I try quick test and it work very well. EasySave.loadTransformsAndInstantiate will be nice:) Thanks a lot for now.
     
  40. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    The update has now been submitted to Unity, so it should hopefully be on the store by the end of Friday.

    @Matis: I've called the function loadTransformArrayAndInstantiate, so once you install the update you will want to use it like this:

    Code (csharp):
    1. if(Input.GetKeyDown(KeyCode.F7))
    2. {  
    3.   instantiatedTiles = EasySave.loadTransformArrayAndInstantiate("transforms.txt", tilePrefab);
    4. }
    Regards,
    Joel
     
  41. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    The new update is now up on the Asset Store, with thanks to the Unity team.
     
  42. 3Duaun

    3Duaun

    Joined:
    Dec 29, 2009
    Posts:
    600
    !! thanks for the work on the update, installing now :)
     
  43. sebako

    sebako

    Joined:
    Jun 27, 2009
    Posts:
    301
    could you let me know when this update is there? I am just hesitating to purchase because of this missing feature :) As soon as its out I will be definetely one of your customers :) Thanks a lot

    edit: is it also possible somehow to store/load gameObjects/prefabs dynamically from the webserver similiar to asset bundles?
     
    Last edited: Oct 28, 2011
  44. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    At the moment we've found no way of doing this as it would require compilation of scripts at runtime, which is something Unity doesn't allow us to do (yet).

    We'll keep you updated on the custom filetype feature!
     
  45. sebako

    sebako

    Joined:
    Jun 27, 2009
    Posts:
    301
    thanks a lot joel, I am waiting for it. One more Question, is it possible to customize php storage? I would like to go with redis instead of mysql, are your php classes open to extend or do I just provide a specific url?
     
  46. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hiya zemog,

    The PHP file is fully customisable commented, so it should be fairly easy to swap the MySQL queries for Redis queries. If you send me an email at moodkie.com/contact, I'll send over the PHP file so you can take a look at it. It's actually a fairly simple file as most of the magic is done at the Unity end.
     
    Last edited: Jun 1, 2017
  47. sebako

    sebako

    Joined:
    Jun 27, 2009
    Posts:
    301
    Okay great, I will just go ahead and purchase. From the overall sound this tool is a good time saver as local storage option which
    I otherwise have to write myself. :) So count me in! ;)
     
  48. Unclet

    Unclet

    Joined:
    Apr 12, 2007
    Posts:
    92
    Easy Save is great! -- took me all of five minutes to get it working in my project. Totally worth $40. Thanks!
     
  49. CoCoNutti

    CoCoNutti

    Joined:
    Nov 30, 2009
    Posts:
    493
    Hi

    I'm just now setting up my Save Game stuff and plan on using Prime31's Game Centre tool etc....

    Just wondering if i need to be aware during setup design of integrating save game detail using Easy Save for Game Centre? (e.g. Achievements and Scores).
     
  50. joeltebbett

    joeltebbett

    Joined:
    Oct 18, 2009
    Posts:
    522
    Hi mangoblue,

    There should be no problems integrating Easy Save with Prime31's Game Centre plugin as Easy Save supports all of Unity's main data types.

    Best wishes,
    Joel