- Home /
Proper way to save ScriptableObjects changed during play mode
I was wondering what the "correct" way to save scriptable objects in Unity that are changed during Play mode. So far I have something that works:
// changes
PartyMember Lalala = PartyMemberDictionary.Find("Lalala");
Lalala.HP += 17;
print("Lalala's HP: " + Lalala.HP);
// then saves
AssetDatabase.Refresh();
EditorUtility.SetDirty(Lalala);
AssetDatabase.SaveAssets();
Note: Lalala is a direct reference to a PartyMember scriptable object in my Assets/Resources folder.
I'm still a little shaky on this approach, however. I got this directly from reading this question:
But the commentator did not explain what each of these three lines of code mean.
AssetDatabase.Refresh();
EditorUtility.SetDirty(Lalala);
AssetDatabase.SaveAssets();
Can someone explain these to me? I'm not sure I understand them fully. I assume "dirty" indicates that data changed; please correct me if I'm wrong.
In this link
https://docs.unity3d.com/ScriptReference/AssetDatabase.SaveAssets.html
it asserts that SaveAssets() saves all unchanged asset changes to disk, so why do I need the other Refresh and SetDirty Functions?
In this link
http://answers.unity3d.com/questions/11531/why-doesnt-my-scriptableobject-save-using-a-custom.html
The OP says "as I found out after some trial and error AssetDatabase.SaveAssets doesn't actually save the asset as expected." ... so confused at this point. That leaves me hesitant to continue until I understand what's going on. Perhaps the Refresh and SetDirty cement the job?
Also, in this link
https://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html
it mentioned that Undo.RecordObject is preferred. Based on your experiences, is this true? Is EditorUtility.SetDirty(); obsolete in this day and age already? I don't want to use it if I have to change my code in the future.
At the end of the day I simply want something that works.
Are you absolutely sure you want to be using ScriptableObjects for this? If you have data that needs to be changed during the actual game runtime, the answer to the previous question is almost always "no". ScriptableObjects are intended to be unchanged during game runtime, and the tools available for changing the data on-the-fly are primarily intended for editor utilities.
If you're trying to save game data to the hard disk, there's a few good ways to do it, one of them being the BinaryFormatter method as described in this official unity tutorial video. With a BinaryFormatter, you can stuff all the data you need to keep track of into a regular ol' class (i.e. a basic class that isn't derived from ScriptableObject or $$anonymous$$onoBehaviour), and the formatter will convert instances of your data class into files on the hard drive.
Thanks for the tip Commoble. Is there a reason why ScriptableObjects are not intended for actual game runtime changes? I'll look into the BinaryFormatter.
From here: https://docs.unity3d.com/$$anonymous$$anual/AssetDatabase.html The AssetDatabase interface is only available in the editor and has no function in the built player
Yep, scriptable objects and these functions are intended for editor purposes only and will not work once you build your project! I believe that scriptable objects get compiled with the rest of the scripts so they cant be changed at runtime(or maybe they can...correct me if I am wrong). So we need an external file to save data which doesnt get compiled and can be changed. To achieve that you create a folder in your assets called Strea$$anonymous$$g Assets(doesnt get compiled) or put your file externally on users device (A dedicated place for saves is Application.persistendatapath! As for the save file creation itself most common approach is to create a json, xml or custom binary file. Here are 6 videos explaining all of it and more (except json but it is similar):https://www.youtube.com/watch?v=-fAqBNeEWjs&list=PL5$$anonymous$$b$$anonymous$$bJ6Gf9_Rvhx1ye1iHxtLTsAaH7uD
Answer by LocalNoob · Jul 31, 2017 at 04:58 PM
What you are doing is intended for in-editor assets management not game saving
From here: https://docs.unity3d.com/Manual/AssetDatabase.html The AssetDatabase interface is only available in the editor and has no function in the built player
Yep, scriptable objects and these functions are intended for editor purposes only and will not work once you build your project! I believe that scriptable objects get compiled with the rest of the scripts so they cant be changed at runtime(or maybe they can...correct me if I am wrong). So we need an external file to save data which doesnt get compiled and can be changed. To achieve that you create a folder in your assets called Streaming Assets(doesnt get compiled) or put your file externally on users device (A dedicated place for saves is Application.persistendatapath! As for the save file creation itself most common approach is to create a json, xml or custom binary file. Here are 6 videos explaining all of it and more (except json but it is similar):https://www.youtube.com/watch?v=-fAqBNeEWjs&list=PL5KbKbJ6Gf9_Rvhx1ye1iHxtLTsAaH7uD
Answer by superfryme · Nov 16, 2018 at 08:46 AM
while your not sure about this code it still worked for my purposes and i will not need to edit it after i build my project. I am using the newest version of unity and those three lines of code still work great. I just replaced the lalala with this.
Your answer
Follow this Question
Related Questions
cloning of ScriptableObject 2 Answers
Problem with ScriptableObject and Custom Editor 2 Answers
UnityScript ScriptableObject error 1 Answer
Importing and using custom assets 0 Answers
Can you use a ScriptableObject to save game state? 6 Answers