Search Unity

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:
    509
    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:
    914
    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:
    509
    Can I have a manager in the additive scene and not in the main scene?
     
  4. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    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:
    509
    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:
    914
    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:
    647
    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:
    8
    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:
    914
    Hi there,

    you can use the Easy Save API from editor scripts.

    All the best,
    Joel
     
  10. JoelAtMoodkie

    JoelAtMoodkie

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

    Are you using the latest version of Easy Save?

    All the best,
    Joel
     
  11. RoosterMai

    RoosterMai

    Joined:
    Nov 6, 2016
    Posts:
    8
    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:
    914
    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:
    647
    Thanks a I noticed that, this is amazing functionality :)
     
    JoelAtMoodkie likes this.
  14. Razputin

    Razputin

    Joined:
    Mar 31, 2013
    Posts:
    356
    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:
    914
    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:
    356
    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:
    914
    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:
    356
    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:
    914
    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:
    914
    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:
    914
    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:
    914
    Hi there,

    Loading is synchronous, so no callback is required.

    All the best,
    Joel
     
  27. cado82

    cado82

    Joined:
    Jul 29, 2020
    Posts:
    25
    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:
    914
    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:
    24
    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:
    914
    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:
    24
    Thanks. I'll try that out.
    That makes sense.

    Rod
     
  32. cryogee

    cryogee

    Joined:
    Aug 6, 2009
    Posts:
    132
    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:
    914
    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
     
  34. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    Hi there I finally managed to create a csv file, edit and load it in the local Unity folder but I prefer to use a single universal location that will work anywhere on any high end platform like PC, Mac, PS4 etc and that the user won't be able to edit.

    I want to have 4 pre-created csv files in the resource folder each representing 1 of the 4 save slots for the user.
    These will be saved and loaded as the player makes progress in the game.

    Is it true that I can use the resources folder to save the CSV file there and then when my game is built not have to worry about any file location issues and if so what is the exact way to do it and what is this nonsense about .byte format wouldn't the csv break if it's saved as .byte etc?

    I assume that if I pre-created the CSV files that instead of:
    public ES3Spreadsheet ES3SaveSlot1 = new ES3Spreadsheet();
    I would use this and drag my precreated CSV file located in the resource folder:
    public ES3Spreadsheet ES3SaveSlot1;

    What about the undocumented "Internal MS" location option what is that?

    Also is this a bug when I followed the tutorial here when I load this file in excel the file does not display the correct values the second cell which should be 12 is replaced by the vector value: https://docs.moodkie.com/easy-save-3/es3-api/es3-methods/es3spreadsheet-constructor/

    P.S. I think the plugin should be named medium save...
    But seriously Unity removed java years ago and many of the documentations use ES2 and some don't even have C# entries like the Spreadsheet examples.
     
    Last edited: Jan 21, 2022
  35. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    Hi there, and thanks for getting in contact.

    To do this you don't need to specify any path. By default files will be stored in Unity's Application.persistentDataPath which does exactly this for any supported platform.

    Note that Unity assets cannot support PS4 storage because they require a middleware license to use their API which they don't provide to Asset Store developers. However, you might be able to integrate this yourself using the instructions here:
    https://docs.moodkie.com/easy-save-3/es3-guides/integrating-storage-apis/

    Resources is just for including files in a build. You cannot store to Resources at runtime. The necessity to have the extension .bytes is defined at Unity's end rather than ours, as Resources is part of their functionality.

    This is only used internally and should not be used. Sadly Unity does not allow us to exclude this option when presenting it in the editor.

    This is expected behaviour because the line which writes the Vector is overwriting the content in the second cell, demonstrating overwriting.

    Code (CSharp):
    1. // Save some values into the spreadsheet.
    2. sheet.SetCell(0,0, "hitpoints");
    3. sheet.SetCell(1,0, 12); // Writes to second cell
    4. sheet.SetCell(0,1, "position");
    5. sheet.SetCell(1,0, transform.position); // Overwrites second cell
    We've had no reports of this, and looking through myself I can't find anywhere in the ES3 docs where this is the case. If you're saying that the Easy Save 3 documentation contains Easy Save 2 code or only has JS examples, please could you tell me where? Are you sure you're not looking at the Easy Save 2 documentation?

    All the best,
    Joel
     
  36. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    That's not good. When I bought this plugin it was advertised as being Cross-platform compatible.
    If I have to create many different save methods for consoles and other platforms then that's a problem.

    1.So lets say I use the Location as "File" and the Directory as "persistent data path" which is usually C:\Users\Name\AppData\LocalLow\CompanyName.... etc that would make it work on all the supported platforms out of the box except the console ones?

    2.And would they all support my CSV file?

    3.If I encrypt it is loading and saving the encrypted file straightforward is the encryption actually good in this day and age?

    4.What's one way I can use that will work really anywhere so it's a one and done thing?

    5.Judging by the confusing documentation I thought that the resources method would be the way to go where I could save the data in the game internally and read and write to it but it seems the documentation is confusing. Who would ever want to save to resources in the editor if you can't read and write to it at runtime they would be setting themselves up for failure right?

    6.So just to be clear even if I have manually created the CSV files I cannot read and write to them via easy save at runtime using resouces?

    7.What about Scriptable Objects would that be one way to read/write data at runtime and have them be inside the game itself and have work anywhere?


    8.As for the documentation it's pretty obvious here's a few with Java only examples:
    https://docs.moodkie.com/easy-save-3/es3-guides/spreadsheets-and-excel/
    https://docs.moodkie.com/easy-save-3/es3-api/es3spreadsheet-class/
    https://docs.moodkie.com/easy-save-3/es3-api/es3-methods/es3spreadsheet-constructor/
    https://docs.moodkie.com/easy-save-3/es3-guides/performance/
    As for the ES2 parts I saw it before but I don't have the time nor interest to find it again and can't confirm if it was old or new documentation but I don't want to start a rant about the documentation as you've been doing this for years and no one seems to complain so it's fine.
     
    Last edited: Jan 22, 2022
  37. JoelAtMoodkie

    JoelAtMoodkie

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

    Just to clarify, we list all compatible platforms at the top of the description on the Asset Store. I've attached a screenshot here and highlighted where it is just in case you missed it (apologies for the poor highlighting, I'm on a trackpad today as it's not a work day :oops:).

    That is correct. See Unity's persistentDataPath docs for information to the precise location it will use for each platform:
    https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html

    Correct.

    It uses AES-128 encryption which is still an industry standard for data obfuscation. In the simplest form you can just

    I'm not sure what you're referring to here. Please could you clarify?

    Resources is a place to include files which you want to include with the build. For example, initialisation data, template data, etc, which is a very common use case for Easy Save. As Resources is part of Unity's functionality rather than ours (we just support it as a storage location), it's worth taking a look at their docs if you feel like you need to include a save file in the build rather than generate it at runtime. Otherwise you don't need to worry about it.

    You can read them at runtime, but you cannot write them. This is a limitation imposed by Unity, not by ourselves, as Resources is part of Unity's functionality. If you want to read and write data, you should use the default save location (Application.persistentDataPath). If you want to include data into a build for initialisation rather than generate it at runtime, you should use Resources.

    You save ScriptableObjects in the same way that you save any other data in Easy Save.

    I think you may be mistaken, all of the examples in all of the links you posted are C#, not JS. I suspect you may be confused because of the 'var' keyword. This is valid C# syntax and is strongly recommended as it reduces errors and duplication without any impact on performance as it is still strongly typed:
    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var

    The 'var' keyword is also used across much of Unity's own C# documentation. For example:
    https://docs.unity3d.com/ScriptReference/Mesh.SetVertexBufferData.html

    Hope this helps clear things up :)

    All the best,
    Joel
     
    SilverStorm likes this.
  38. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    I think I'm beginning to really get it now.
    For question 3 you cut out at the end did you mean to say more?

    For Question 4 I meant it looks like persistentdatapath is the best I was just wondering if there's a better option practically for the save format as sooner or later one will encounter some kind of platform they have to port things over for but you've said something about binary format before and how that can be used by consoles as well so if I change my save format from csv to a .bin file does that mean it can stay in the persistendatapath and also be used by consoles?
    Most platforms can use CSV but I don't think consoles like Switch, Xbox and Ps4/Ps5 will so I would like a format that is used by anything at least that way if I have to port the games save file I only need to change the save location and it should all work.
     
  39. JoelAtMoodkie

    JoelAtMoodkie

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

    Apologies, I’m not sure what happened there :) I meant to say that in its simplest form you can just enable encryption from Tools > Easy Save 3 > Settings. You’ll need to delete your previous save data by going to Tools > Easy Save 3 > Clear PersistentDataPath, as this will contain unencrypted data and throw an error if you try to load it with encryption enabled.

    I think you maybe be getting the conversation about Resources mixed up with the conversation about consoles.

    The reason we can’t support PlayStation isn’t anything to do with format. It’s that PlayStation has its own Storage APIs which require a middleware license to use (it’s illegal to use them otherwise). As they are unwilling to provide middleware licenses to Unity Asset Store publishers, it’s impossible for an Asset Store tool to support them out of the box. However, we provide instructions here on how you might integrate it with their Storage APIs yourself:
    https://docs.moodkie.com/easy-save-3/es3-guides/integrating-storage-apis/

    You may be able to get additional support from the PlayStation developer forums and PlayStation themselves.

    The above also applies for Nintendo, but not Xbox as long as you’re using the UWP API.

    All the best,
    Joel
     
    SilverStorm likes this.
  40. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    Hi, I am wondering if there is a way for us to load a key without creating the object immediately.

    Both ES3.LoadRawString and ES3.LoadRawBytes load the whole cache, which means we have to create multiple cache (multiple ES3 settings) instead of using a single cache.
     
  41. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    So I wanted to create an in-memory cache using ES3 that will serialize/deserialize gameobject and return me a byte array (similar to the "integrating with other storage API" guide).

    Yet it seems I cannot just create an ES3 in-memory storage (ES3.Location.InternalMS), I have to use the cache (ES3.Location.Cache) and supply a permanent path name and check for its existence.

    But I just want an in-memory store, and no need to flush data into files, is there any API that can help me to do so?
     
  42. JoelAtMoodkie

    JoelAtMoodkie

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

    You can use ES3.Serialize and ES3.Deserialize to serialise and deserialise individual pieces of data to strings which you can then do with what you want.

    All the best,
    Joel
     
  43. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    Thx, one follow up question:

    Does ES3.LoadInto<GameObject>(key, target, settings) update component and hierarchy of the target object?

    I tried to do this but it seems target transform isn't updated.
     
  44. JoelAtMoodkie

    JoelAtMoodkie

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

    This is indeed the case and can be tested by attaching the following script to any GameObject:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class LoadIntoGO : MonoBehaviour
    4. {
    5.     void Start()
    6.     {
    7.         this.transform.position = Vector3.one;
    8.         ES3.Save("go", this.gameObject);
    9.  
    10.         var newGo = new GameObject();
    11.         newGo.transform.position = Vector3.zero;
    12.  
    13.         ES3.LoadInto("go", newGo);
    14.         Debug.Assert(newGo.transform.position == this.transform.position);
    15.     }
    16. }
    If this isn't happening for you, it's likely that something else is controlling the Transform. Are you able to replicate your issue in a new project?

    All the best,
    Joel
     
  45. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    I wanted to ask a quick question regarding saving to a file while it is open in use.
    The Unity console gives an error if I try to save my csv file while I have opened it in Excel as windows doesn't allow certain actions to a file while it is open in use what would you recommend i do to save the game while the file is open and in use to prevent interruption of gameplay?

    I don't think encryption will help either because u can still open an encrypted file to view it even if the content is nonsense so Unity will still say file is open and in use.

    Maybe there's a line of code that I can use that checks if the file is open and in use and if it is being used by windows then the game will tell you it cannot save at this time etc or maybe you know a better way?

    What about code that says if easysave cannot read/save the file it is corrupted etc how does it handle things like this without screwing up game play?
     
  46. JoelAtMoodkie

    JoelAtMoodkie

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

    In these cases you would use a try/catch block to catch the exception and throw an appropriate error the user saying that it can't be saved because the file is open elsewhere.

    All the best,
    Joel
     
  47. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961

    Thx, indeed it was my mistakes.

    Sorry for yet another question: it seems for the same data, ES3.Load() is able to always find the right gameobject instance to overwrite, I wonder what data does this magic rely on?

    (My observation is, if I serialize a gameobject and then load it twice, it results in 1 single gameobject, no duplicates.)
     
  48. JoelAtMoodkie

    JoelAtMoodkie

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

    Easy Save has it's own reference manager which it uses to resolve references at runtime (as far as we're aware, we're the only asset capable of doing this).

    All the best,
    Joel
     
  49. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    Any chance you can paste a code snippet of this try catch block you are talking about?
     
  50. JoelAtMoodkie

    JoelAtMoodkie

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


    Code (CSharp):
    1. try
    2. {
    3.     // Your Easy Save code
    4. }
    5. catch(System.IO.IOException)
    6. {
    7.     // Display your error message
    8. }
    All the best,
    Joel
     
    SilverStorm likes this.