Every video/guide about why you should use Scriptable Objects seems to very quickly gloss over the fact that the data in a Scriptable Object does not get reset when you exit play mode in Unity.
i.e. If I have player health stored in an SO and I enter play mode to test/debug my game, and my player loses some health in that play session, the health in the SO stays at that level next time I enter play mode. Obviously making it a nightmare to play test and debug.
Potential Solution 1 - Create Instances
I’ve seen some people say they just create an instance of the SO at runtime, then the changes get made to that instance and the instance dies when you exit play mode so you’re all good… but that seems to have a huge problem unless I’m missing something. In most cases we’re using SOs to hold shared data, so if you create a separate instance then that’s no longer shared data - its a unique instance and other items referencing the SO will not see the same data. Now of course you could just create one instance and have all your other components refer to that one instance, but aren’t you basically ending up with a singleton and defeating the point of using SOs in the first place?
Potential Solution 2 - Reset Values To Defaults
So given how bad the first “solution” seems to be, this is the only real option I can think of. The idea being that you have a script that runs when the game first loads (or on a per scene basis) and automatically resets values on every SO to be their correct default values.
But where should that script get its values from? Obviously I want to avoid hard coding them in the script. So these are the two best options I can think of:
-
It could pull them from an external file (XML etc) that I manually set the correct default values in.
-
Instead of getting the values from an external file, the script would reference another SO in my project that acts as a “template”. This template SO would never be referenced elsewhere in my code so it would stick to whatever values I enter in the designer and never change. This approach seems better as it keeps everything easily visible and editable in the Unity designer, but it also feels a bit hacky and weird having to create two SOs for every SO. They would both be holding essentially the same data but one of them I just let get messed up by play testing and one of them I have to remember to never drag into any scenes or access in code (other than the initial loading script). Doesn’t that end up being just as bad as using uninstantiated prefabs instead of SOs, where you have to remember certain prefabs are “special” and not to be used in scenes like others. I guess I could just have one master “default settings” SO that contains default values for all other SOs, and the script reads from that and populates the relevant SOs, which feels a bit less weird but still not ideal.
With either of those options though there’s several issues I’m not keen on or unsure about. Like how this means for every single SO in the entire game, I need to remember to add its default values to my template/master list, and then add code to reset it to those values.
So yeah I’m keen to hear how other people deal with this stuff in the real world, and if I’m on the right track or if there’s some better alternative I’ve not thought of (quite likely). I should point out I’m very new to game development (but have several years of experience with .NET desktop app development) so by all means correct things I’ve got wrong or point me in a different direction if I’m suggesting doing things in a weird way