Scriptable object persisting data. Bug or feature?

Hi. So whenever I edit a scriptable object variable, the new value persists through the Unity session. This means that if I have a scriptable object with a string value of “John”, and during runtime I change that value to “Steve” through code by doing something like myScriptableObject.name = "Steve"; then I stop playing, and play it again, the value will still be “Steve”. However, if I restart Unity, the name will be “John” again.

Is this a bug or a feature?

Thanks.

1 Like

It’s correct behavior. I guess you would call it a feature.
The reason it reverts to John after reloading unity is when you changed it to Steve, you didn’t dirty the scriptable object.

When unity exits (without crashing) or you hit “save project” unity writes dirty object values to disk.

Since the object is not being set dirty from your runtime script, unity doesn’t know anything has changed, so Steve is never written to disk.

Solution… Use EditorUtility.SetDirty(yourObjectReference) after changing the value.

Note this is editor only. If you change to Steve in built player. Steve will persist through the game session. If you close the app, the value will be John again

8 Likes

Thanks for replying. That helped a lot. :wink:

In the Editor you should always instantiate scriptableobject before using it.

Only if you are modifying it. There is no reason to instantiate immutable data ScriptableObjects, I would treat the mutation to be a bug in most of those uses.

1 Like

This feature is really useful in order to allow live-editing of gameplay elements that persist after play mode. We usually set up UI settings (sizes, timings, etc.) in a ScriptableObject. The UI uses those settings, and listens to a callback on the SO that we invoke when we change it, so the changes live update.

1 Like

I am making a project for drawing with the vector graphics package. I create my tools using scriptable objects, so I can set cursors for each one and other settings they may need. In my shape tool, I have an auto property used to define what shape is supposed to be drawn(uses an Enum.) I would select one shape, draw it. Then select another shape, draw that one and stop playing to make some changes. Every time I did this the last shape would be the one selected not the one I set as default. The only way to get it to revert the property back to default was to shut down the editor and start it back up again(domain reload.)

In conclusion, ScriptableObjects get loaded in the editor and retain their values until a domain reload. In my case I don’t want it to save or retain the changes, thus the use of an auto property. Had me scratching my head as to why Unity would be able to serialize a property when I know it can’t.

Just to frustrate you a little bit more, this isn’t strictly true. Unity does serialize private fields during domain reload, and that does include auto property backing fields. Generally, anything you can see with the debug inspector is serialized, just not to disk. To lose those changes you need Unity to reload the asset from disk, as private fields are not serialized to disk.

1 Like

It’s only a small caveat with SO’s in the editor. Once you understand that any SO shown in the inspector is deserialized and loaded into memory and remains in memory until the asset gets unloaded. If you have a reference to an SO in a scene it will also be deserialized with the scene when it gets deserialized.

Lokking just for conformation ( or - hopefully not - dissent ), you can prevent serialization of private fields on SO’s by using the**[NonSerialized]**Attribute … correct ?

Indeed.

So to add to this, how can I mark a field to not be persisted but still show up in the inspector?