Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Does SerializedObject.ApplyModifiedProperties work on all changes?

Discussion in 'Scripting' started by Silly_Rollo, Mar 26, 2017.

  1. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    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.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    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:
    https://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html

    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:
     
    Kshesho, Pacosmico and fhamel_bhvr like this.
  3. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    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.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    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.
     
    Pacosmico likes this.
  5. Silly_Rollo

    Silly_Rollo

    Joined:
    Dec 21, 2012
    Posts:
    501
    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.
     
    qsp18 likes this.
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    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.
     
    Pacosmico and dval like this.
  7. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    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
     
    Judkins and pfay like this.
  8. pfay

    pfay

    Joined:
    Mar 2, 2020
    Posts:
    7
    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).
     
    Judkins likes this.