Does SerializedObject.ApplyModifiedProperties work on all changes?

The doc is pretty much empty on this. Does this apply all changes made to an object ala EditorUtility.SetDirty or does this only apply/save the changes made through SerializedProperties?

I ask because I have editor scripts that when certain changes occur go ahead and modify additional properties on an object (accessing the object directly and setting the values, not through SerializedProperties). After the changes are made I call ApplyModifiedProperties on the SerializedObject the properties belong to but I want to make sure all my changes are being serialized.

So far everything on the object looks right but I don’t want to find later a bunch of changes evaporate when the editor is closed.

Making those changes via SerializedProperty would be a lot more convoluted as I don’t see a way to take a serialized class instance (a custom class marked serializable) and turn it into a SerializedProperty. I also need to access a function on the class (which there isn’t a simple way to do on a SerializedProperty) so I guess I’d have to pass around both the instance of the class and the SerializedProperty it is attached to which isn’t ideal.

If it matters these are all on ScriptableObjects so there are no scene issues.

ApplyModifiedProperties applies the changes of the SerializedObject to the actual object.

Basically it’s like this… the SerializedObject is a representation of the serialized data for a given object (or objects if isEditingMultipleObjects is true). And then there is the actual object. They are distinct from one another in memory.

SerializedObject.Update takes the current state of the real object, and updates the SerializedObject so that it has the same state.

ApplyModifiedProperties goes the opposite direction, it takes the current state of the SerializedObject, and updates the real object, so that it has the same state.

Note… EditorUtility.SetDirtry is considered sort of out dated, and shouldn’t be used unless you don’t have an option:

It basically is flagging an object as dirty so that unity knows it should save the new state to disk. It’s sort of like ā€˜Update’, but more passively done. Instead of saying to unity ā€œhey, this needs to be saved to diskā€ā€¦ you’re instead flagging it as needing to be saved, and unity will get to it when it gets to it.

Hence why Unity says in the doc that:

4 Likes

So that’s a yes? Any changes made to the object whether through SerializedProperty or not are applied to the saved data if it is just making sure the two match? What I was afraid was happening was that properties that were not marked as modified (through the mechanism of SerializedProperty) were being ignored when the serialized object was being updated.

No… it doesn’t make sure the 2 match.

It applies one to the other.

Update applies the real object to the SerializedObject.

ApplyModifiedProperties applies the SerializedObject to the real object.

One overwrites the other.

1 Like

It looks like the answer is no. Change a value directly (not through serializedproperty) and then call ApplyModifiedProperties and the on disk value is not changed. Since a SO is just a text file I forgot I could just open it in a text editor and there it was plain to see the value was not changed. If you change something via SerializedProperty (e.g. property.intValue = 1) and then call ApplyModifiedProperties the value is changed on disk.

This suggests it doesn’t just completely overwrite the serialized disk representation with the current object but performs some sort of ā€˜is this property changed’ checking and only overwrites values it knows were changed. Using the old SetDirtry every value on disk is updated so ApplyModifiedProperties is different.

It is possible some there is some interaction with editor scripts or forced text serialization I’m not considering but since SerializedProperty is the way going forward I should just accept passing those around.

1 Like

yeah, if you change the value directly on the real object, and then use ApplyModifiedProperties, the serialized object doesn’t receive that changed value… because ApplyModifiedProperties doesn’t do that. Update takes the real objects values and applies them to the serializedobject… ApplyModifidiedProperties applies the serializedobject values to the real object.

Yeah… ApplyModifiedProperties is different from SetDirty.

SetDirty flags the REAL object as dirty, so that unity knows to update the serialized representation of the object, using the state of the real object.

ApplyModifiedProperties, sets the real object with the data in the SerializedObject.

These are OPPOSITE things.

SetDirty = real → serial
ApplyModifiedProperties = serial → real
Update = real → serial

And of course… serial technically is 2 parts. There’s the on disk, and the SerializedObject. Because SerializedObject is just the memory representation of the on disk representation.

I’m not 100% certain at what step unity actually commits the SerializedObject to disk… if it’s on Update, ApplyModifiedProperties, or some other time.

2 Likes

Is it AssetDatabase.SaveAssets(); ?

like so in my editor I have a serializedObject, which I update at the start of my inspector and then ApplyModifiedProperties after detecting changes using EndChangeCheck. This updates the object from the serialized object. then I guess AssetDatabase.SaveAssets() saves the object to the asset? i thought that maybe the serialized object represented the asset but it feels like that’s wrong now

2 Likes

SerializedObject.ApplyModifiedProperties() into AssetDatabase.SaveAssets() did it for me.

I believe SerializedObject.ApplyModifiedProperties() applies dirty changes to the object in editor memory, (so if you use that asset in your game it should work if you hit play), and then the AssetDatabase.SaveAssets() actually writes dirty assets to disk (so you will have them on a restart / can commit them to source control).

1 Like