Search Unity

  1. The 2022.1 beta is now available for testing. To find out what's new, have a look at our 2022.1 beta blog post.
    Dismiss Notice

Easy Save - The Complete Save Data & Serialization Asset

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

  1. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    497
    Hi,

    I was wondering if I can have the Easy Save 3 Manager in a separate additive scene where I put all of the common objects I use in every scene. The reason why Im wondering this is because ES3Manager keeps a list of references of the scene objects, so I'm not sure if I can put it in an empty scene and still be able to use it to save player and npc data.
     
  2. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    The manager works with additive scenes and will merge the one in the additive scene with the one in the main scene.

    All the best,
    Joel
     
  3. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    497
    Can I have a manager in the additive scene and not in the main scene?
     
  4. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    You can, but no references from the main scene will be in the reference manager.

    All the best,
    Joel
     
  5. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    497
    Okay, last question - what's the point of these references? Can I still save my data without them?
     
  6. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    They allow things to be stored by reference. If you’re only storing value types, this is not required, otherwise it is.

    All the best,
    Joel
     
    skinwalker likes this.
  7. Jakub_Machowski

    Jakub_Machowski

    Joined:
    Mar 19, 2013
    Posts:
    520
    Hello @JoelAtMoodkie
    Is there a way to access easy save variable load but in-editor to use it in some editor tools? or load some game settings to be loaded when using editor not playmode?
     
  8. RoosterMai

    RoosterMai

    Joined:
    Nov 6, 2016
    Posts:
    4
    Hi @JoelAtMoodkie
    I add a list to Dictionary<string, object>, when i save and load, it will throw FormatException: Expected '{' or "null", found '['.
    Code (CSharp):
    1.             var a = new Dictionary<string, object>();
    2.             a.Add("a", 1);
    3.             var value = new List<string>() {"Hello", "You"};
    4.             a.Add("b", value);
    5.             ES3.Save("Test", a);
    6.             ES3.Load("Test");
     
    Last edited: Dec 28, 2021
  9. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    you can use the Easy Save API from editor scripts.

    All the best,
    Joel
     
  10. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    Are you using the latest version of Easy Save?

    All the best,
    Joel
     
  11. RoosterMai

    RoosterMai

    Joined:
    Nov 6, 2016
    Posts:
    4
    Yes, I use 3.3.2f7. It should be easy to reproduct it.
    And it's the save file, i think the ES3 try to parse 'b' as Object, so try to find '{', but find the '['
     

    Attached Files:

  12. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    I don’t appear to be getting this issue on our upcoming update which indicates that it’s resolved there. If you private message me your invoice number, I’ll send over this update.

    All the best,
    Joel
     
  13. Jakub_Machowski

    Jakub_Machowski

    Joined:
    Mar 19, 2013
    Posts:
    520
    Thanks a I noticed that, this is amazing functionality :)
     
    JoelAtMoodkie likes this.
  14. Razputin

    Razputin

    Joined:
    Mar 31, 2013
    Posts:
    267
    What is the default location spreadsheets are loaded from?

    Sheet.Load("test.csv"); for example, would be located where?

    Can you load into ES3Spreadsheets from resources?
     
  15. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    By default the storage location is Unity's Application.persistentDataPath. However, ES3Spreadsheet also accepts relative or absolute paths if you want to specify your own path. Please see the documentation on paths for more information:

    https://docs.moodkie.com/easy-save-3/es3-guides/settings-paths-locations/

    You can also load spreadsheets from resources. Please see the Saving and Loading from Resources guide for more information:

    https://docs.moodkie.com/easy-save-3/es3-guides/saving-loading-resources/

    All the best,
    Joel
     
  16. Razputin

    Razputin

    Joined:
    Mar 31, 2013
    Posts:
    267
    Presumably this should log something then? I only get null references atm.

    Code (CSharp):
    1.        
    2.  
    3.         var settings = new ES3Settings();
    4.         settings.location = ES3.Location.Resources;
    5.         spreadSheet.Load("csvtest");
    6.  
    7.         Debug.Log(spreadSheet);
    8.  
     
  17. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    You need to create the spreadsheet before trying to load something into it. Please see the spreadsheet docs for more information:
    https://docs.moodkie.com/easy-save-3/es3-guides/spreadsheets-and-excel/

    You're also not providing the ES3Settings object you've created as a parameter to the Load method, meaning it's not doing anything.

    All the best,
    Joel

    All the best,
    Joel
     
  18. Razputin

    Razputin

    Joined:
    Mar 31, 2013
    Posts:
    267
    Creating the spreadsheet was the issue, working now, thank you.
     
    JoelAtMoodkie likes this.
  19. Razheem

    Razheem

    Joined:
    Sep 15, 2017
    Posts:
    7
    HI @JoelAtMoodkie !

    Discovering Easy save this morning and passing Unity certification in about a month.

    I managed so far to get everything running fine except one thing : scriptable objects.

    I have a script that references all my scriptables (a simple market script that check an int "energy" to make a boolean true or false), added it in auto save, made sure with the cog that every fields are checked...

    In editor everything is fine (scriptables...)
    But in build, nothing works with my scriptables =(
    Too bad because i managed to get prefabs instancies work, i though this would be the hard part...

    Any idea to avoid me from doing this from scratch ? ^^

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. namespace ES3Types
    5. {
    6.     [UnityEngine.Scripting.Preserve]
    7.     [ES3PropertiesAttribute("_energy", "_iron", "_planetsBools", "_sitesPlanet1Bools", "_droneTypesBools", "_droneSpeedBools", "_planet2LockObject", "_planet3LockObject", "_droneTypeMinerLockObject", "enabled", "name")]
    8.     public class ES3UserType_UIMarketManager : ES3ComponentType
    9.     {
    10.         public static ES3Type Instance = null;
    11.  
    12.         public ES3UserType_UIMarketManager() : base(typeof(UIMarketManager)){ Instance = this; priority = 1;}
    13.  
    14.  
    15.         protected override void WriteComponent(object obj, ES3Writer writer)
    16.         {
    17.             var instance = (UIMarketManager)obj;
    18.          
    19.             writer.WritePrivateFieldByRef("_energy", instance);
    20.             writer.WritePrivateFieldByRef("_iron", instance);
    21.             writer.WritePrivateFieldByRef("_planetsBools", instance);
    22.             writer.WritePrivateFieldByRef("_sitesPlanet1Bools", instance);
    23.             writer.WritePrivateFieldByRef("_droneTypesBools", instance);
    24.             writer.WritePrivateFieldByRef("_droneSpeedBools", instance);
    25.             writer.WritePrivateFieldByRef("_planet2LockObject", instance);
    26.             writer.WritePrivateFieldByRef("_planet3LockObject", instance);
    27.             writer.WritePrivateFieldByRef("_droneTypeMinerLockObject", instance);
    28.             writer.WriteProperty("enabled", instance.enabled, ES3Type_bool.Instance);
    29.         }
    30.  
    31.         protected override void ReadComponent<T>(ES3Reader reader, object obj)
    32.         {
    33.             var instance = (UIMarketManager)obj;
    34.             foreach(string propertyName in reader.Properties)
    35.             {
    36.                 switch(propertyName)
    37.                 {
    38.                  
    39.                     case "_energy":
    40.                     reader.SetPrivateField("_energy", reader.Read<RessourcesInts>(), instance);
    41.                     break;
    42.                     case "_iron":
    43.                     reader.SetPrivateField("_iron", reader.Read<RessourcesInts>(), instance);
    44.                     break;
    45.                     case "_planetsBools":
    46.                     reader.SetPrivateField("_planetsBools", reader.Read<BoolVariables>(), instance);
    47.                     break;
    48.                     case "_sitesPlanet1Bools":
    49.                     reader.SetPrivateField("_sitesPlanet1Bools", reader.Read<BoolVariables>(), instance);
    50.                     break;
    51.                     case "_droneTypesBools":
    52.                     reader.SetPrivateField("_droneTypesBools", reader.Read<BoolVariables>(), instance);
    53.                     break;
    54.                     case "_droneSpeedBools":
    55.                     reader.SetPrivateField("_droneSpeedBools", reader.Read<BoolVariables>(), instance);
    56.                     break;
    57.                     case "_planet2LockObject":
    58.                     reader.SetPrivateField("_planet2LockObject", reader.Read<UnityEngine.GameObject>(), instance);
    59.                     break;
    60.                     case "_planet3LockObject":
    61.                     reader.SetPrivateField("_planet3LockObject", reader.Read<UnityEngine.GameObject>(), instance);
    62.                     break;
    63.                     case "_droneTypeMinerLockObject":
    64.                     reader.SetPrivateField("_droneTypeMinerLockObject", reader.Read<UnityEngine.GameObject>(), instance);
    65.                     break;
    66.                     case "enabled":
    67.                         instance.enabled = reader.Read<System.Boolean>(ES3Type_bool.Instance);
    68.                         break;
    69.                     default:
    70.                         reader.Skip();
    71.                         break;
    72.                 }
    73.             }
    74.         }
    75.     }
    76.  
    77.  
    78.     public class ES3UserType_UIMarketManagerArray : ES3ArrayType
    79.     {
    80.         public static ES3Type Instance;
    81.  
    82.         public ES3UserType_UIMarketManagerArray() : base(typeof(UIMarketManager[]), ES3UserType_UIMarketManager.Instance)
    83.         {
    84.             Instance = this;
    85.         }
    86.     }
    87. }
    Also my bool scriptable

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. [CreateAssetMenu]
    5.  
    6. public class BoolVariables : ScriptableObject
    7. {
    8.     public bool _bool2;
    9.     public bool _bool3;
    10.     public bool _bool4;
    11.     public bool _bool5;
    12.     public bool _bool6;
    13.     public bool _bool7;
    14.     public bool _bool8;
    15. }
    And finally my int variable, so simple, so classy :p


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu]
    6. public class RessourcesInts : ScriptableObject
    7. {
    8.     public int value;
    9.  
    10. }
    Really hoping you'll get me through this, project showcase is in 4 days !
     
    Last edited: Jan 3, 2022
  20. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    We’ve had no other reports of this. Are you getting any warnings or errors in the console/log file for the platform you’re targeting?

    All the best,
    Joel
     
  21. Razheem

    Razheem

    Joined:
    Sep 15, 2017
    Posts:
    7
    Nope, not a single error...

    Here let me pass the persistant data path :


    Mono path[0] = 'D:/Unity/0AAAAABUILDSAAAAA0/FinalProject3WAINERTIA_Data/Managed'
    Mono config path = 'D:/Unity/0AAAAABUILDSAAAAA0/MonoBleedingEdge/etc'
    Initialize engine version: 2020.3.20f1 (41c4e627c95f)
    [Subsystems] Discovering subsystems at path D:/Unity/0AAAAABUILDSAAAAA0/FinalProject3WAINERTIA_Data/UnitySubsystems
    GfxDevice: creating device client; threaded=1
    d3d11: QueryInterface(IDXGIFactory5) failed (80004002).
    Direct3D:
    Version: Direct3D 11.0 [level 11.0]
    Renderer: NVIDIA GeForce GTX 770 (ID=0x1184)
    Vendor:
    VRAM: 1947 MB
    Driver: 23.21.13.9135
    Begin MonoManager ReloadAssembly
    - Completed reload, in 0.074 seconds
    <RI> Initializing input.

    <RI> Input initialized.

    <RI> Initialized touch support.

    UnloadTime: 0.812941 ms
    ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
    at ES3Internal.ES3Stream.CreateStream (ES3Settings settings, ES3Internal.ES3FileMode fileMode) [0x00105] in <100b91fbc95046bcaddffaa76a62626f>:0
    at ES3Reader.Create (ES3Settings settings) [0x00000] in <100b91fbc95046bcaddffaa76a62626f>:0
    at ES3.Load[T] (System.String key, T defaultValue, ES3Settings settings) [0x00017] in <100b91fbc95046bcaddffaa76a62626f>:0
    at ES3AutoSaveMgr.Load () [0x0002b] in <100b91fbc95046bcaddffaa76a62626f>:0
    at ES3AutoSaveMgr.Awake () [0x00052] in <100b91fbc95046bcaddffaa76a62626f>:0

    Unloading 6 Unused Serialized files (Serialized files now loaded: 0)
    Shader 'FORGE3D/Planets/SphereMap': fallback shader 'None' not found
    UnloadTime: 4.029577 ms
    Reference with ID 8590292066164654778 could not be found in Easy Save's reference manager. If you are loading objects dynamically (i.e. objects created at runtime), this warning is expected and can be ignored.
    <i>To disable warnings from Easy Save, go to Window > Easy Save 3 > Settings, and uncheck 'Log Warnings'</i>
    Reference with ID 2847465875929362852 could not be found in Easy Save's reference manager. If you are loading objects dynamically (i.e. objects created at runtime), this warning is expected and can be ignored.
    <i>To disable warnings from Easy Save, go to Window > Easy Save 3 > Settings, and uncheck 'Log Warnings'</i>

    Unloading 7 unused Assets to reduce memory usage. Loaded Objects now: 3320.
    Total: 2.520791 ms (FindLiveObjects: 0.150469 ms CreateObjectMapping: 0.043033 ms MarkObjects: 2.293039 ms DeleteObjects: 0.034251 ms)

    Setting up 4 worker threads for Enlighten.
    Thread -> id: 4444 -> priority: 1
    Thread -> id: 373c -> priority: 1
    Thread -> id: 2848 -> priority: 1
    Thread -> id: 462c -> priority: 1

    I'm getting tired, cya tomorrow (in 4hours in France :p)
     
  22. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    You appear to be getting an error and a warning in what you’ve pasted above.

    I recommend clearing the save data on the device as the error suggests that you have encryption or compression enabled, but the data on your device was a unencrypted/uncompressed, or vice versa.

    All the best,
    Joel
     
  23. Razheem

    Razheem

    Joined:
    Sep 15, 2017
    Posts:
    7
    Hi Joel, thank you for your replies.

    I cleared data and changed it to location file with encryption.
    I did not found any reference in the savefile.es3 for my scriptables nor my UIMarket script, only for my prefabs...
    I tried building only with the scene market but nothing works.

    Can i make a package and sent it to you to see what's wrong, or meet on discord to get rid of this ?
    I'm total newbie for permanent data, i'm afraid to start JSON while i have so much to do in leveldesign =(

    Now i got this in the log

    Code (CSharp):
    1. egin MonoManager ReloadAssembly
    2. - Completed reload, in  0.100 seconds
    3. <RI> Initializing input.
    4.  
    5. <RI> Input initialized.
    6.  
    7. <RI> Initialized touch support.
    8.  
    9. UnloadTime: 0.970436 ms
    10. ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
    11.   at ES3Internal.ES3Stream.CreateStream (ES3Settings settings, ES3Internal.ES3FileMode fileMode) [0x00105] in <100b91fbc95046bcaddffaa76a62626f>:0
    12.   at ES3Reader.Create (ES3Settings settings) [0x00000] in <100b91fbc95046bcaddffaa76a62626f>:0
    13.   at ES3.Load[T] (System.String key, T defaultValue, ES3Settings settings) [0x00017] in <100b91fbc95046bcaddffaa76a62626f>:0
    14.   at ES3AutoSaveMgr.Load () [0x0002b] in <100b91fbc95046bcaddffaa76a62626f>:0
    15.   at ES3AutoSaveMgr.Awake () [0x00052] in <100b91fbc95046bcaddffaa76a62626f>:0
    16.  
    17. ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
    18.   at ES3Internal.ES3Stream.CreateStream (ES3Settings settings, ES3Internal.ES3FileMode fileMode) [0x00105] in <100b91fbc95046bcaddffaa76a62626f>:0
    19.   at ES3Reader.Create (ES3Settings settings) [0x00000] in <100b91fbc95046bcaddffaa76a62626f>:0
    20.   at ES3Writer.Merge () [0x00000] in <100b91fbc95046bcaddffaa76a62626f>:0
    21.   at ES3Writer.Save (System.Boolean overwriteKeys) [0x00003] in <100b91fbc95046bcaddffaa76a62626f>:0
    22.   at ES3Writer.Save () [0x00000] in <100b91fbc95046bcaddffaa76a62626f>:0
    23.   at ES3.Save[T] (System.String key, T value, ES3Settings settings) [0x0002b] in <100b91fbc95046bcaddffaa76a62626f>:0
    24.   at ES3AutoSaveMgr.Save () [0x000b9] in <100b91fbc95046bcaddffaa76a62626f>:0
    25.   at ES3AutoSaveMgr.OnApplicationQuit () [0x00009] in <100b91fbc95046bcaddffaa76a62626f>:0
     
  24. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    If you're able to replicate this in a brand new project with a simple scene I'm happy to take a look at it if you private message it to me with instructions.

    All the best,
    Joel
     
  25. JLemmens

    JLemmens

    Joined:
    Aug 24, 2020
    Posts:
    9
    Hi, bought the asset yesterday and had a question i couldn't find an answer to in the documentation.
    Is there some sort of Callback that can be attached to a Load method call? just to be 100% sure the data i requested is loaded in, and not run into timing issues.

    Thanks for the great asset!
     
  26. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    Loading is synchronous, so no callback is required.

    All the best,
    Joel
     
  27. cado82

    cado82

    Joined:
    Jul 29, 2020
    Posts:
    20
    Hi, can you please help me to understand the use case of caching when using auto save?

    From my understanding Auto Save is only saving the data during the save event (e.g. OnApplicationPause) or when calling ES3AutoSaveMgr.Current.Save() explicitly. I can see that in the ES3AutoSaveMgr.Current.Save method the file is cached before calling ES3.Save and then ES3.StoreCachedFile is called but as the save is just one operation would I be right in saying there's no benefit here?

    I want to support automatic saving when important data is changed in my mobile game (such as when a player levels) and I'm coming to the realisation that auto save may not be best for that but correct me if I'm wrong. Is ES3AutoSaveMgr.Current.Save designed in such a way that it's expected to be called in a situation like that or am I best saving everything manually with ES3.Save with Caching enabled and then calling ES3.StoreCachedFile when I hit an important milestone that I want saving? I don't want to be saving all the data in my game if just one thing is changed. Is Easy Save smart enough to only change the things that have changed since the last save or is the whole file written each time?

    Thanks,
     
  28. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    It depends on how many different scenes you’re Auto Saving. Each Auto Save manager saves to a different key, and caching is beneficial in situations where you’re using multiple keys. It can also be used to defer the write to file to a time which is less critical (for example when changing scenes or exiting the application).

    Regarding Auto Saving when an individual piece of data changes, it would indeed be more efficient to save the single piece of data using caching, but you may find that Auto Save causes no noticeable drop in performance and might be easier in your case. I would only worry about making things more complex if your testing has it uncovered performance issues.

    All the best,
    Joel
     
  29. VastnessVR

    VastnessVR

    Joined:
    Nov 21, 2017
    Posts:
    23
    Hi Joel,
    Just trying to work out loading some values.

    I have this line of code that works great if the data is in the file, otherwise, it throws an exception.

    CompletionsToFinishLevels = ES3.Load<Dictionary<int, int>>("CompletionsToFinishLevels");

    But want to add a default value that if there is no value it will use the default.
    The popup shows 8 options. Number 4 shows
    Dictionary<int, int> ES3.Load<Dictionary<int, int>>(String key, Dictionary<int, int> DefaultValue);
    So that would be
    CompletionsToFinishLevels = ES3.Load<Dictionary<int, int>>("CompletionsToFinishLevels", 30);
    or
    CompletionsToFinishLevels = ES3.Load<Dictionary<int, int>>("CompletionsToFinishLevels", Dictionary<int, int> 30);

    Both show errors.

    Any suggestions?
    Rod
     
  30. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    Regarding your first attempt, the default value would need to be the same type as the data you’re loading, not an int.

    Regarding your second line of code, I’m not sure what you’re trying to do here. It doesn’t seem to be valid C#. If you’re trying to initialise the Dictionary, I recommend looking at guides on how to initialise a Dictionary.

    Generally you would do something like this:

    CompletionsToFinishLevels = ES3.Load<Dictionary<int, int>>("CompletionsToFinishLevels", myDefaultDictionary);

    … where myDefaultDictionary is a dictionary of the same type which you’ve initialised elsewhere.

    All the best,
    Joel
     
  31. VastnessVR

    VastnessVR

    Joined:
    Nov 21, 2017
    Posts:
    23
    Thanks. I'll try that out.
    That makes sense.

    Rod
     
  32. cryogee

    cryogee

    Joined:
    Aug 6, 2009
    Posts:
    119
    Hello -

    Im using ES3 to save world-level information. How many levels are there and if they are unlocked and how many stars are collected etc.

    So I have generated this saved file in 'persistent data path' in Editor. What is the best way to include this in builds on phones?

    Do I copy the file when user first time loads the game into phone's persistent path or is there a way to read the file from say 'Assets/Levels/level.es3'
     
  33. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    762
    Hi there,

    You would generally do this using Unity’s Resources folder. You can find information on loading from the Resources folder here:
    https://docs.moodkie.com/easy-save-3/es3-guides/saving-loading-resources/

    All the best,
    Joel
     
unityunity