Search Unity

Easy Save - The Complete Save Data & Serialization Asset

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

  1. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Code (CSharp):
    1.         static public string MCInfo = "MC DataPackage";
    2.         static public int MCVersion = 12;
    3.  
    4.         static readonly public int KeySetMax = 64;       // 64 Sets
    5.         static readonly public int KeyVarMax = 128;      // 128 Variables
    6.         static readonly public int KeyFrameMax = 48;     // 48 Per Set
    7.  
    8.         public enum TR_Typ { Float = 0, Vector2 = 1, Vector3 = 2, Vector4 = 3, Color = 4 };
    9.  
    10.         static public int[,] Key_IsTyp = new int[KeySetMax, KeyVarMax];
    11.         static public int[,] TR_Activate = new int[KeySetMax, KeyVarMax];
    12.         static public int[,] TR_ShowCurveOrGradient = new int[KeySetMax, KeyVarMax];
    13.         static public float[,,] KeyTime = new float[KeySetMax, KeyVarMax, KeyFrameMax];
    14.         static public string[,] KeySetVarName = new string[KeySetMax, KeyVarMax];
    15.         static public Vector2[,] KeySetVarMinMax = new Vector2[KeySetMax, KeyVarMax];
    16.         static public Vector4[,] KeySetVarStart = new Vector4[KeySetMax, KeyVarMax];
    17.         static public Vector4[,] KeySetVarEnd = new Vector4[KeySetMax, KeyVarMax];
    18.  
    19.         // ... Path_File = Application.dataPath + "/Resources/multicurvedata.bytes";
    20.         static public void SaveMCData(string Path_File) {
    21.         #if UNITY_EDITOR
    22.             if (dataIsLoaded) {
    23.                 var settings = new ES3Settings();
    24.                 settings.location = ES3.Location.File;
    25.                 var file = new ES3File(Path_File, settings);
    26.                 file.Save<string>("MCInfo", MCInfo);
    27.                 file.Save<int>("MCVersion", MCVersion);
    28.  
    29.                 file.Save<float[,,]>("MC.KeyTime[]", KeyTime);
    30.                 file.Save<Vector4[,,]>("MC.KeyValue[]", KeyValue);
    31.                 file.Save<Vector2[]>("MC.KeySetTimeFromTo[]", KeySetTimeFromTo);
    32.  
    33.                 String1DArrayNullTo(ref KeySetName, "");
    34.                 file.Save<string[]>("MC.KeySetName[]", KeySetName);
    35.  
    36.                 String2DArrayNullTo(ref KeySetVarName, "");
    37.                 file.Save<string[,]>("MC.KeySetVarName[]", KeySetVarName);
    38.  
    39.                 file.Save<int[,]>("MC.Key_IsTyp[]", Key_IsTyp);
    40.                 file.Save<Vector4[,]>("MC.KeySetVarStart[]", KeySetVarStart);
    41.                 file.Save<Vector4[,]>("MC.KeySetVarEnd[]", KeySetVarEnd);
    42.                 file.Save<Vector2[,]>("MC.KeySetVarMinMax[]", KeySetVarMinMax);
    43.                 file.Save<int[,]>("MC.TR_Activate[]", TR_Activate);
    44.                 file.Sync();
    45.                 AssetDatabase.Refresh();
    46.  
    47.                 Debug.Log("* ES3 SAVE MultiCurveData Successfully saved to : " + Path_File + "  *");
    48.             } else {
    49.                 Debug.LogError("* ES3  Error: SaveMCData() Data fieds are not initalized. Can't Save.");
    50.             }
    51.             #endif
    52.         }
    53.  
     
    Last edited: Sep 3, 2020
  2. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    Thanks for sending that over. Unfortunately without being able to see where the bottleneck is in the profiler it's hard for me to tell how to improve performance. However, be aware that AssetDatabase.Refresh() can be very intensive, so it's worth checking that it's not causing your slow down.

    All the best,
    Joel
     
  3. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Impossible, while profiling with or without AssetDatabase.Refresh Unity hangs because pumping about 13GB into memory. I could only see shortly that ES3 was involved. All in a blank project. Copy and paste the small code into you script and execute. Doesn't matter what unity version you use.

    You can simply use :
    SaveMCData(string Path_File);
    LoadMCData(string Path_File);

    Thank you.

    Untitled-1.jpg

    Complete script
    Code (CSharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public static class TestES3Quatum
    6. {
    7.    static public bool editorIsOpen = false;
    8.    static public bool dataIsLoaded = false;
    9.  
    10.    static public string MCInfo = "MC DataPackage";
    11.    static public int MCVersion = 12;
    12.  
    13.    static readonly public int KeySetMax = 64;       // 64 Sets
    14.    static readonly public int KeyVarMax = 128;      // 128 Variables
    15.    static readonly public int KeyFrameMax = 48;     // 48 Per Set
    16.  
    17.    public enum TR_Typ { Float = 0, Vector2 = 1, Vector3 = 2, Vector4 = 3, Color = 4 };
    18.  
    19.    static public int[,] Key_IsTyp = new int[KeySetMax, KeyVarMax];
    20.    static public int[,] TR_Activate = new int[KeySetMax, KeyVarMax];
    21.    static public int[,] TR_ShowCurveOrGradient = new int[KeySetMax, KeyVarMax];
    22.    static public float[,,] KeyTime = new float[KeySetMax, KeyVarMax, KeyFrameMax];
    23.    static public string[,] KeySetVarName = new string[KeySetMax, KeyVarMax];
    24.    static public Vector2[,] KeySetVarMinMax = new Vector2[KeySetMax, KeyVarMax];
    25.    static public Vector4[,] KeySetVarStart = new Vector4[KeySetMax, KeyVarMax];
    26.    static public Vector4[,] KeySetVarEnd = new Vector4[KeySetMax, KeyVarMax];
    27.    static public Vector4[,,] KeyValue = new Vector4[KeySetMax, KeyVarMax, KeyFrameMax];
    28.    static public Vector2[] KeySetTimeFromTo = new Vector2[KeySetMax];
    29.    static public string[] KeySetName = new string[KeySetMax];
    30.  
    31.    static public bool LoadMCData(string Path_File)
    32.    {
    33.        // ... Path_File = Application.dataPath + "/Resources/multicurvedata.bytes";
    34.        var settings = new ES3Settings();
    35.        settings.location = ES3.Location.File;
    36.  
    37.        if (ES3.FileExists(Path_File))
    38.        {
    39.            var file = new ES3File(Path_File, settings);
    40.  
    41.            if (file.KeyExists("MCInfo"))
    42.            {
    43.                var info = file.Load<string>("MCInfo", "");
    44.                if (info != MCInfo)
    45.                {
    46.                    dataIsLoaded = false;
    47.                    return dataIsLoaded;
    48.                }
    49.            }
    50.  
    51.            var version = file.Load<int>("MCVersion", -1);
    52.            if (version != MCVersion)
    53.            {
    54.            }
    55.  
    56.            KeyTime = file.Load<float[,,]>("MC.KeyTime[]");
    57.            KeyValue = file.Load<Vector4[,,]>("MC.KeyValue[]");
    58.            KeySetTimeFromTo = file.Load<Vector2[]>("MC.KeySetTimeFromTo[]");
    59.            KeySetName = file.Load<string[]>("MC.KeySetName[]");
    60.            KeySetVarName = file.Load<string[,]>("MC.KeySetVarName[]");
    61.            Key_IsTyp = file.Load<int[,]>("MC.Key_IsTyp[]");
    62.            KeySetVarStart = file.Load<Vector4[,]>("MC.KeySetVarStart[]");
    63.            KeySetVarEnd = file.Load<Vector4[,]>("MC.KeySetVarEnd[]");
    64.            KeySetVarMinMax = file.Load<Vector2[,]>("MC.KeySetVarMinMax[]");
    65.            TR_Activate = file.Load<int[,]>("MC.TR_Activate[]");
    66.  
    67.            file.Sync();
    68.  
    69.            dataIsLoaded = true;
    70.  
    71.            Debug.Log("* ES3 LOAD MultiCurveData Succsessfully From : " + Path_File + "  *");
    72.  
    73.            return true;
    74.        }
    75.  
    76.        dataIsLoaded = false;
    77.        return false;
    78.    }
    79.  
    80.  
    81.    // ... Path_File = Application.dataPath + "/Resources/multicurvedata.bytes";
    82.    static public void SaveMCData(string Path_File)
    83.    {
    84.        dataIsLoaded = true;
    85.        if (dataIsLoaded)
    86.        {
    87.            var settings = new ES3Settings();
    88.            settings.location = ES3.Location.File;
    89.            var file = new ES3File(Path_File, settings);
    90.            file.Save<string>("MCInfo", MCInfo);
    91.            file.Save<int>("MCVersion", MCVersion);
    92.  
    93.            file.Save<float[,,]>("MC.KeyTime[]", KeyTime);
    94.            file.Save<Vector4[,,]>("MC.KeyValue[]", KeyValue);
    95.            file.Save<Vector2[]>("MC.KeySetTimeFromTo[]", KeySetTimeFromTo);
    96.  
    97.            String1DArrayNullTo(ref KeySetName, "");
    98.            file.Save<string[]>("MC.KeySetName[]", KeySetName);
    99.  
    100.            String2DArrayNullTo(ref KeySetVarName, "");
    101.            file.Save<string[,]>("MC.KeySetVarName[]", KeySetVarName);
    102.  
    103.            file.Save<int[,]>("MC.Key_IsTyp[]", Key_IsTyp);
    104.            file.Save<Vector4[,]>("MC.KeySetVarStart[]", KeySetVarStart);
    105.            file.Save<Vector4[,]>("MC.KeySetVarEnd[]", KeySetVarEnd);
    106.            file.Save<Vector2[,]>("MC.KeySetVarMinMax[]", KeySetVarMinMax);
    107.            file.Save<int[,]>("MC.TR_Activate[]", TR_Activate);
    108.            file.Sync();
    109.            AssetDatabase.Refresh();
    110.  
    111.            Debug.Log("* ES3 SAVE MultiCurveData Successfully saved to : " + Path_File + "  *");
    112.        }
    113.        else
    114.        {
    115.            Debug.LogError("* ES3  Error: SaveMCData() Data fieds are not initalized. Can't Save.");
    116.        }
    117.    }
    118.  
    119.    /// <summary>
    120.    /// 1D String Array fill with a string
    121.    /// </summary>
    122.    /// <param name="mystring"></param>
    123.    /// <param name="s"></param>
    124.    public static void String1DArrayNullTo(ref string[] mystring, string s)
    125.    {
    126.        for (int i = 0; i < mystring.GetLength(0); i++)
    127.        {
    128.            if (mystring[i] == null)
    129.            {
    130.                mystring[i] = s;
    131.            }
    132.        }
    133.    }
    134.  
    135.    /// <summary>
    136.    /// 2D String Array fill with a string
    137.    /// </summary>
    138.    /// <param name="mystring"></param>
    139.    /// <param name="s"></param>
    140.    public static void String2DArrayNullTo(ref string[,] mystring, string s)
    141.    {
    142.        int idx0 = 0;
    143.        int idx1 = 0;
    144.        for (idx0 = 0; idx0 < mystring.GetLength(0); idx0++)
    145.        {
    146.            for (idx1 = 0; idx1 < mystring.GetLength(1); idx1++)
    147.            {
    148.                if (mystring[idx0, idx1] == null)
    149.                {
    150.                    mystring[idx0, idx1] = s;
    151.                }
    152.            }
    153.        }
    154.    }
    155. }
    156.  
     
    Last edited: Sep 3, 2020
  4. JoelAtMoodkie

    JoelAtMoodkie

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

    I've had no other reports of this behaviour and don't seem to be able to replicate it at my end.

    Could you let me know how you saw that ES3 was involved? If you could private message me the blank project you're using I'll see if it's anything project-specific.

    Please could you also go to Window > Easy Save 3 > Tools > Open Persistent Data Path and let me know the size of the file which is being saved.

    All the best,
    Joel
     
  5. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Sorry, I really don't understand what you want to tell me. Why didn't install this script. Takes < 1 minute. Then you see the results on iOS or PC. In this time you write the last comment, you have tested it already and see the result. You can be assured it's the same on every machine.
     
  6. JoelAtMoodkie

    JoelAtMoodkie

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

    Just to clarify, I had tested your script and I'm not getting the same memory usage as you've described in the profiler, so I was asking for a sample project to see what is different about the project you're using.

    As mentioned in my first post, the bottleneck is the quantity of data you're saving, as you're saving 843,776 items of varying data types. Binary formatting isn't going to make a significant amount of difference because even binary formatting has to write formatted data to the file.

    One thing you can try is to increase the buffer size in Window > Easy Save 3 > Settings > Advanced Settings, to minimise the number of times the buffer needs to be flushed. However, this would increase your memory usage.

    All the best,
    Joel
     
  7. liquidsht

    liquidsht

    Joined:
    Jun 4, 2020
    Posts:
    49
    Hi I am just starting EasySave. I currently have 2 scenes, 1st scene is called NeverUnload, it holds camera, UI , Player and other things that i keep across scenes. 2nd scene is just called Scene1, which holds the level and enemies. This is my code for Save and Load:
    Code (CSharp):
    1. public class EasySave : MonoBehaviour
    2. {
    3.     public GameObject Player;
    4.    
    5.     void Update()
    6.     {
    7.         if(Input.GetKeyDown(KeyCode.P))
    8.         {
    9.            Save();
    10.         }
    11.     }
    12.     public void Save()
    13.     {
    14.         HealthWithCameraShakeExtension health = Player.GetComponent<HealthWithCameraShakeExtension>();
    15.         ES3.Save("SavedScene",SceneManager.GetActiveScene().name);
    16.         ES3.Save("PlayerPosition", Player.transform.position);
    17.         ES3.Save("InitialHealth", health.InitialHealth);
    18.         ES3.Save("MaximumHealth", health.MaximumHealth);
    19.     }
    20. }
    Code (CSharp):
    1. public class EasyLoad : MonoBehaviour
    2. {
    3.     public GameObject Player;
    4.     public string levelToLoad;
    5.     void Update()
    6.     {
    7.         if (Input.GetKeyDown(KeyCode.O))
    8.         {
    9.             Debug.Log("Game Loaded");
    10.             Load();//loads saved scene
    11.             LoadNeverUnload(); //load neverunload additively
    12.             LoadPlayerPosition(); //load players position
    13.         }
    14.     }
    15.     public void Load()
    16.     {
    17.         HealthWithCameraShakeExtension health = Player.GetComponent<HealthWithCameraShakeExtension>();
    18.  
    19.         levelToLoad = ES3.Load<string>("SavedScene");      
    20.         SceneManager.LoadScene(levelToLoad);
    21. health.InitialHealth = ES3.Load<int>("InitialHealth");
    22.         health.MaximumHealth = ES3.Load<int>("MaximumHealth");
    23.     }
    24.     public void LoadNeverUnload()
    25.     {
    26.         SceneManager.LoadScene("NeverUnload", LoadSceneMode.Additive);
    27.         Debug.Log("Load Neverunload");
    28.     }
    29.  
    30.     public void LoadPlayerPosition()
    31.     {
    32.         Player.transform.position = ES3.Load<Vector3>("PlayerPosition");
    33.     }
    34. }
    I have no issue saving the game, but loading is a problem.

    My load game logic flows like this, load Scene 1 which contains the level and enemies, load player max and initial health, load the player position but I cant seem to load the saved position of the player. When I load, the player is at original position. I have checked the save file and saved position of the player is not the original position.

    I am loading the NeverUnload scene additively as I am not sure if there is a way for EasySave to load 2 scenes together, if it can, then may be there is a better way?
     
  8. JoelAtMoodkie

    JoelAtMoodkie

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

    Would you be able to change your LoadPlayerPosition() method to the following and let me know the output to console?


    Code (CSharp):
    1. public void LoadPlayerPosition()
    2. {
    3.      var oldPosition = Player.transform.position;
    4.      var newPosition = ES3.Load<Vector3>("PlayerPosition");
    5.      Debug.Log("Old position: "+oldPosition+", New position:"+newPosition);
    6.      Player.transform.position = newPosition;
    7. }
    8.  
    All the best,
    Joel
     
  9. liquidsht

    liquidsht

    Joined:
    Jun 4, 2020
    Posts:
    49
    Thanks for the quick response,i got the following:

    Old position: (28.8, -22.7, 0.0), New position: (23.3, -31.7, 0.0)
    UnityEngine.Debug:Log(Object)
    EasyLoad:LoadPlayerPosition() (at Assets/Scripts/EasyLoad.cs:40)
    EasyLoad:Update() (at Assets/Scripts/EasyLoad.cs:17)
     
    Last edited: Sep 4, 2020
  10. JoelAtMoodkie

    JoelAtMoodkie

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

    This shows that the data being loaded from Easy Save isn't the original position, so it's being loaded correctly and is unlikely to be an issue at our end.

    Are you sure that the position isn't being reset anywhere in your code, and that you're assigning the position to the correct object?

    Also one thing to note: if your object is a child of another object, you might want to use localPosition rather than position.

    All the best,
    Joel
     
  11. Jh2556

    Jh2556

    Joined:
    Sep 29, 2014
    Posts:
    18
    Hi @JoelAtMoodkie, thanks for the great asset! I had a question.

    I'm looking to have multiple save slots, which can easily be done with using files and different paths. On top of that I'd like to store global game settings(audio level, subtitles on, which save slot file to load, etc), so those should be a in a separate file from game progress.

    It looks like since E3 is static I can't have references to multiple files open at once? I looked at the CacheFIle and that didn't seem it'd help here either. Am I understanding this all correctly?

    ---

    Would the proper way to handle this be to 1. On game start up load the settings file, 2. load the data from the settings save file into some sort of game Settings object, 3. Load the game save slot file.

    I think that'd work mostly OK, but the bump I see is if any settings were changed mid game. In that situation I'd need to 1. Save the game save slot. 2. Load the settings file, 3. save and update the settings file with the info from the game Settings object, 4. Reload the game save slot.

    I don't think this would be an issue, just a few hoops to jump through.

    Thanks!!
     
    Last edited: Sep 12, 2020
  12. JoelAtMoodkie

    JoelAtMoodkie

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

    The Easy Save 3 methods have a filePath parameter, so you just need to set this to a different filename accordingly. For example:

    Code (CSharp):
    1. ES3.Save("myKey", 123, "SaveSlot1.es3");
    2. ES3.Save("myGlobalKey", 456, "Globals.es3");
    For more information please see the 'Changing the filename or path' section of the Getting Started guide:
    https://docs.moodkie.com/easy-save-3/getting-started/#changing-the-filename-or-path

    All the best,
    Joel
     
  13. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Hi @JoelAtMoodkie

    I have an error "Value cannot be null." for dictionary with my SO and int type.

    On the Moodkit forum and Unity I cannot find any info about solution. Are yoyu able to say what is the problem and how to solve it?

    Unity 2019.4.9f1
    ES: 3.3.1f9
     
  14. JoelAtMoodkie

    JoelAtMoodkie

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

    This is a very generic error message so it's not possible for me to tell what is happening from what you've said. Please could you post the full stack trace of the error message?

    All the best,
    Joel
     
  15. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Below is the stack trace:

    Code (CSharp):
    1. Value cannot be null.
    2.  
    3. Parameter name: key  at System.Collections.Generic.Dictionary`2[TKey,TValue].System.Collections.IDictionary.Add (System.Object key, System.Object value) [0x00003] in <fb001e01371b4adca20013e0ac763896>:0
    4.   at ES3Types.ES3DictionaryType.Read (ES3Reader reader) [0x0005f] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\Collection Types\ES3DictionaryType.cs:101
    5.   at ES3Types.ES3Type.ReadProperties (ES3Reader reader, System.Object obj) [0x0033b] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3Type.cs:149
    6.   at ES3Types.ES3ReflectedObjectType.ReadObject[T] (ES3Reader reader) [0x0000d] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\Reflected Types\ES3ReflectedObjectType.cs:27
    7.   at ES3Types.ES3ObjectType.Read[T] (ES3Reader reader) [0x00044] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3ObjectType.cs:54
    8.   at ES3Reader.ReadObject[T] (ES3Types.ES3Type type) [0x00017] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Readers\ES3Reader.cs:249
    9.   at ES3Reader.Read[T] (ES3Types.ES3Type type) [0x0007e] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Readers\ES3Reader.cs:278
    10.   at ES3Types.ES3Type.ReadProperties (ES3Reader reader, System.Object obj) [0x00390] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3Type.cs:154
    11.   at ES3Types.ES3ReflectedComponentType.ReadComponent[T] (ES3Reader reader, System.Object obj) [0x00001] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\Reflected Types\ES3ReflectedComponentType.cs:24
    12.   at ES3Types.ES3ComponentType.ReadUnityObject[T] (ES3Reader reader, System.Object obj) [0x00001] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3ComponentType.cs:36
    13.   at ES3Types.ES3UnityObjectType.ReadObject[T] (ES3Reader reader, System.Object obj) [0x00001] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3UnityObjectType.cs:50
    14.   at ES3Types.ES3ObjectType.ReadInto[T] (ES3Reader reader, System.Object obj) [0x00044] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Types\ES3ObjectType.cs:77
    15.   at ES3Reader.ReadObject[T] (System.Object obj, ES3Types.ES3Type type) [0x0000d] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Readers\ES3Reader.cs:239
    16.   at ES3Reader.ReadInto[T] (System.Object obj, ES3Types.ES3Type type) [0x00060] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\Readers\ES3Reader.cs:292
    17.   at ES3.DeserializeInto[T] (ES3Types.ES3Type type, System.Byte[] bytes, T obj, ES3Settings settings) [0x00023] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3.cs:780
    18.   at ES3.DeserializeInto[T] (System.Byte[] bytes, T obj, ES3Settings settings) [0x00001] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3.cs:770
    19.   at ES3File.LoadInto[T] (System.String key, T obj) [0x0007e] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3File.cs:264
    20.   at GarrisonController.LoadData (ES3File file) [0x0000e] in PATH_TO_PROJECT\Assets\Project\Scripts\Core\MapSystem\GarrisonController.cs:110
    Regards,
    Marcin
     
  16. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    Thanks for sending that over. The most likely cause for this is that the key for one of the Dictionary items in a Dictionary you are saving is a reference which no longer exists. To look into this further, would you be able to create a new project with a simple scene which replicates this and private message it to me?

    All the best,
    Joel
     
  17. Jh2556

    Jh2556

    Joined:
    Sep 29, 2014
    Posts:
    18
    Ah, perfect @JoelAtMoodkie!! I see I can also load directly from a path which solved all my issues. Thanks so much!
     
    JoelAtMoodkie likes this.
  18. KarlKarl2000

    KarlKarl2000

    Joined:
    Jan 25, 2016
    Posts:
    606
  19. JoelAtMoodkie

    JoelAtMoodkie

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

    You can find instructions on this in the 'Configuring Auto-Cloud for Unity Applications' section of Steam's Cloud documentation:
    https://partner.steamgames.com/doc/features/cloud#steam_auto-cloud

    Hope this helps!

    All the best,
    Joel
     
  20. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Hi @JoelAtMoodkie

    I changed the implementation and problem disappear. However, I have another problem.

    I have a following scenes:
    - MainMenu (scene in build)
    - Managers (addressable)
    - Scene A (addressable)
    - Scene B (addressable)

    MainMenu loads by addressable mechanism Managers scene. Later it loads Scene A and Scene B. After loading all scenes I get the following error (2 times):

    Code (CSharp):
    1. ArgumentNullException: Value cannot be null.
    2. Parameter name: key
    3.   at System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) [0x00008] in <4756199cf52a4f14b33cdcc5659f782e>:0
    4.   at System.Collections.Generic.Dictionary`2[TKey,TValue].set_Item (TKey key, TValue value) [0x00000] in <4756199cf52a4f14b33cdcc5659f782e>:0
    5.   at ES3Internal.ES3ReferenceMgrBase.Add (UnityEngine.Object obj, System.Int64 id) [0x00068] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3ReferenceMgrBase.cs:230
    6.   at ES3Internal.ES3ReferenceMgrBase.Merge (ES3Internal.ES3ReferenceMgrBase otherMgr) [0x00018] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3ReferenceMgrBase.cs:116
    7.   at ES3Internal.ES3ReferenceMgrBase.Awake () [0x00037] in PATH_TO_PROJECT\Assets\3rd-Party\Easy Save 3\Scripts\ES3ReferenceMgrBase.cs:100
    I check the id of the null value and this is the ID of Manager scene. Both errors are in Easy Save Manager which is on Manager scene.

    Are you able to say where is the source of the problem?

    Best regards,
    Marcin
     
  21. KarlKarl2000

    KarlKarl2000

    Joined:
    Jan 25, 2016
    Posts:
    606
  22. JoelAtMoodkie

    JoelAtMoodkie

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

    The most likely cause of this error is because an object which has been marked as destroyed is being saved. However, it's not possible to tell for certain as this very much depends on how your project operates.

    Would you be able to private message me a new project with basic scenes to replicate this?

    All the best,
    Joel
     
  23. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Hi @JoelAtMoodkie

    How can i save a string to a file (and not in a key inside that file)
    and Similarly how can i load whole file back to a string?

    Please provide the functions?

    What i dont want is this
    ES3.Save("myKey", myValue, "myFolder/myFile.es3");

    But rather
    ES3.Save(myValue, "myFolder/myFile.es3");
    and similarly ES3.Load<string>("myFolder/myFile.es3");

    And secondly, how do i get FileInfo object for this saved file? so i can check
    FileInfo.LastWriteTime
     
    Last edited: Sep 23, 2020
  24. JoelAtMoodkie

    JoelAtMoodkie

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

    This is covered in the documentation here:
    https://docs.moodkie.com/easy-save-3/es3-guides/saving-loading-strings-bytes-file/

    Regarding getting the FileInfo, you would need to use the C# method for this which is documented here:
    https://docs.microsoft.com/en-us/dotnet/api/system.io.fileinfo?view=netcore-3.1

    By default files are saved in Application.persistentDataPath, so you would need to supply Application.persistentDataPath + "/YourFileName.txt" as the parameter to the FileInfo object.

    All the best,
    Joel
     
    jGate99 likes this.
  25. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Thanks Joel
     
  26. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    BTW, it'd be great if you provide the path as you already provide an ES3File,Exists like function which meanss you already make a proper path
     
  27. JoelAtMoodkie

    JoelAtMoodkie

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

    FileInfo isn't part of our API, which is why you would need to provide the full path yourself.

    All the best,
    Joel
     
    jGate99 likes this.
  28. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Sorry for confusing, what i'm trying to say is that ES3 providing absolute path to file would be great, just like it has
    ES3.FileExists so something like ES3.GetFileAbsoulatePath.


    than developer manually building absolute path and running into issues.
     
  29. JoelAtMoodkie

    JoelAtMoodkie

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

    We've never had issues with people constructing their own path. If people do start running into this problem we'll definitely consider adding it, but we'd rather only add methods that there's a need for so that we're not adding unnecessary noise to the documentation :)

    However, you can do this yourself using (new ES3Settings(yourFilename)).FullPath.

    All the best,
    Joel
     
    jGate99 likes this.
  30. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Thanks Joel, above snippet is great and solves the problem :)

    Now one last question,
    I can use ES3.FileExists before i do this?
    ES3.LoadRawString("myFile.txt")

    or is there a seperate function
     
  31. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    Glad to hear it :)

    ES3.FileExists works with any type of file, so you can use it to check whether your raw file exists.
     
    jGate99 likes this.
  32. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Awesome, and thanks for your prompt support
     
  33. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Hi Joel,

    I will try to preare a small project.

    Best,
    Marcin
     
  34. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Hi @JoelAtMoodkie

    In the meantime I have some questions about references.

    I load scriptable objects (SO) by Unity Addressable system. When I save the game I can see in the file a reference to my SO. However, when I start the game and load game from save file the refrences to my SO are not in the ES3GlobalReferences file and I get null values.

    So my questions:
    1) When ES3GlobalReferences file is updated in editor?
    2) How IDs are generated? I am afraid of chaning theirs IDs between builds.
    3) Is it possible to add dynamicly loaded file to references? If yes, will IDs always be the same for this case?

    Best,
    Marcin
     
  35. JoelAtMoodkie

    JoelAtMoodkie

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

    Reference managers are updated when you hit play in the Editor, and when you build your project. IDs will not change between builds unless you delete the object to which they refer.

    It's possible to dynamically add a reference using ES3ReferenceMgr.Current.Add(obj, id), but it would be up to you to ensure that you use the same ID each time.

    Just to clarify, if you're using addressables then there will not be a reference to your ScriptableObject in the scene prior to runtime. This means that it's not possible for the reference manager to know that you want to add this object. To add it you can right-click the ScriptableObject and press Easy Save 3 > Add Reference(s) to Manager.

    Hope this helps.

    All the best,
    Joel
     
  36. KrejwenBAN

    KrejwenBAN

    Joined:
    Jun 8, 2020
    Posts:
    8
    Hi @JoelAtMoodkie

    Ok, so it means that I have to store in each object it uniqes ID. How the system reatcs when there are duplicates IDs?

    I have also a question about ES3GlobalReferences. This SO has references to all object in my project. So when I start the game this SO is initialized and all objects are in memory even if I not used them. Am I correct?

    Best,
    Marcin
     
  37. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    I'm afraid I'm not sure what you mean by this.
    The new ID will overwrite the old ID. However, all IDs will be unique unless you're adding the references to the manager yourself.
    ES3GlobalReferences isn't used at runtime. This is only used when Easy Save adds a reference to the manager in the Editor in order to assign the same ID across scenes.

    Where possible I recommend adding your ScriptableObject to the manager by right-clicking it and selecting Easy Save 3 > Add Reference(s) to Manager. This handles the logic for you so you don't have to worry about these sorts of questions.

    All the best,
    Joel
     
  38. trurl22

    trurl22

    Joined:
    Mar 3, 2015
    Posts:
    2
    Hi, been using the asset and it's all around great. I've got some beginner questions...
    Q1: I have to load 1-2K bools at startup, which takes about 8 seconds. Would it do anything for performance if I were to shove them into a couple of arrays instead, and only save/load those? Asking because it's too large a job to do blindly.
    Q2: Is the ES3 Manager object that adds itself to scenes safe to delete? I noticed it slowed build time significantly, so hoping for a yes. Thank you.
     
    Last edited: Sep 30, 2020
  39. JoelAtMoodkie

    JoelAtMoodkie

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

    Putting the bools in an array would help, or alternatively you can use caching:
    https://docs.moodkie.com/easy-save-3/es3-guides/performance/

    With regards to the Easy Save 3 Manager, you only need this if you're saving reference types or using Auto Save.

    All the best,
    Joel
     
    trurl22 likes this.
  40. Apollo11_1969

    Apollo11_1969

    Joined:
    Nov 20, 2018
    Posts:
    15
    Hi

    Is it possible to save/modify individual high-score values for example, on a remote webserver, (without uploading an entire file or syncing from a local file on a PC)? If so can you point me to the relevant region of the documentation please?

    Thank you

    Jeff
     
  41. JoelAtMoodkie

    JoelAtMoodkie

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

    Easy Save's web functionality is only intended as cloud storage, so the only way to do this would be to save each value to a separate file and upload these separately.

    All the best,
    Joel
     
  42. Apollo11_1969

    Apollo11_1969

    Joined:
    Nov 20, 2018
    Posts:
    15
    OK Joel. Thank you.

    Jeff
     
  43. yomanx

    yomanx

    Joined:
    Dec 5, 2016
    Posts:
    38
    Friends, what about iOS 14 bugs?
    After reinstalling the game, my SAVES are not loaded.
     
  44. JoelAtMoodkie

    JoelAtMoodkie

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

    We've had no reports of issues on iOS 14, and it appears to work fine at our end. The only time the data will be deleted is if you've changed the bundle identifier of the app, or if you deleted the app and the data wasn't stored to cloud.

    All the best,
    Joel
     
  45. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    Hi @JoelAtMoodkie

    // Save the string as a file.
    ES3.SaveRaw(myString, "myFile.txt");

    How can i use this function and ask it to save in compressed form to save storage space
     
  46. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    jGate99 likes this.
  47. yomanx

    yomanx

    Joined:
    Dec 5, 2016
    Posts:
    38
    Hmm, i found strange things:
    1) When i install game by xcode - everything works perfect, i get my saves.

    2) When i install game by TestFlight - i get each time NEW CLEARED save.
    Founds that my device id after the each TF reinstall getting New.

    The same bundle identifier used.
     
    Last edited: Oct 1, 2020
  48. JoelAtMoodkie

    JoelAtMoodkie

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

    You can use Application.persistentDataPath to see if the path is changing between Xcode and TF builds. I.e.

    Code (CSharp):
    1. Debug.Log(Application.persistentDataPath);
    All th ebest,
    Joel
     
  49. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
  50. JoelAtMoodkie

    JoelAtMoodkie

    Joined:
    Oct 18, 2009
    Posts:
    914
    You can use the same instance.

    All the best,
    Joel
     
    jGate99 likes this.