- Home /
Confirm serialized property before changing it in a custom editor
I want to confirm the changing of the serialized property before applying it to the required field in this editor script:
using UnityEngine;
using UnityEditor;
public class SetFields : EditorWindow
{
/// <summary>
/// The component that has the serialized object the we want to set.
/// </summary>
private SerializedObject myTarget;
/// <summary>
/// The serialized object the we want to set.
/// </summary>
private SerializedProperty fieldNewValue;
[MenuItem("Tools/Set Fields")]
public static void ShowWindow() => GetWindow<SetFields>("Set Fields");
private void OnGUI()
{
try
{
myTarget = new SerializedObject("some component");
fieldNewValue = myTarget.FindProperty("some field");
EditorGUILayout.PropertyField(fieldNewValue, new GUIContent("Value", "The field new value."), true);
myTarget.ApplyModifiedProperties();
}
catch (System.Exception) { }
}
}
The thing is this updates the field in real time, and I don't want that, I want to apply the value to the field when the user clicks a button in the custom editor window, but if I put "myTarget.ApplyModifiedProperties();" inside a button like this :
if (GUILayout.Button("Set Field Value"))
{
myTarget.ApplyModifiedProperties();
}
The value in the custom editor window will always revert back to its original.
Answer by Bunny83 · Nov 05, 2021 at 10:34 AM
Yes, this wont work. The SerializedObject and its SerializedProperties are just wrapper classes that represent the state of the serialized data. When you create the SerializedObject, it automatically calls Update to actually read the serialized state into its properties. Now you can modify those properties and when done you call ApplyModifiedProperties to actually write those changes back to the serialized data.
However your code is executed for every UI interaction. That means if you don't apply the changes you made through the PropertyField, those changes are lost since the next time this method is called for example when you click on the button, the changes are no longer there since you have a new SerializedObject / SerializedProperty.
It's not clear how the exact flow of your editor window should look like and where you get that "some component" from. However usually you would create the SerializedObject only once when you select that object.
Though even if you did create the SerializedObject only once and keep reusing it, you run into other issues. When the object is modified elsewhere (the inspector or at runtime from the runtime code itself) the state of your SerializedObject would not update. That's why you usually call Update at the beginning of OnGUI and ApplyModifiedProperties at the end.
You talked about a verification process but you haven't gone into any details what this is actually about. We don't even know the type of your property. Verification is usually done right in place when the assignment happens. Of course when you use a PropertyField this is actually delegated to a PropertyDrawer. So you have to do the verification after the method returns. If you need to revert invalid changes, you would need to store the previous value before you call the PropertyField in a local variable so you can revert the changes after the method. Though if the verification is just some sort of clamping you can just do it afterwards.
If you really want some sort of apply button, you would also need a seperate button to "Update" the state manually. I haven't looked into details how Unity's TextureInspector does it, but I guess it's something like this:
void OnGUI()
{
if (!SerializedObject.hasModifiedProperties)
serializedObject.Update();
// [ ... ]
// the actual GUI goes here.
// [ ... ]
using (new EditorGUI.DisabledScope(!SerializedObject.hasModifiedProperties))
{
if (GUILayout.Button("Revert"))
serializedObject.Update();
if (GUILayout.Button("Apply"))
serializedObject.ApplyModifiedProperties();
}
}
So as long as nothing got modified we automatically update the serialized object so it reflects the actual current state of the object and if something is changed elsewhere, when your editor window is redrawn it will reflect the current state. However when you actually change any property in your SerializedObject it will no longer update itself but instead enables the two buttons at the bottom to either revert the canges (by manually updating the serializedObject) or to apply the changes.
Of course this still requires you to clear up the actual information flow of your editor window which includes where and how it actually gets the object you want to "inspect".
Thank you very much for the detailed answer,
updating the serialized object manually like you said did the trick, for clarification I'm making an editor window that changes the value of a field for a multiple component instances, I know this is something unity do by default, however this is not the case with my component, changing a field value of multiple instances changes only the first selected one, so I created this editor window. link text
"You talked about a verification process but you haven't gone into any details what this is actually about" the verification is not for integrity of data or something, it is for stopping the editor window from updating the serialized property in real time, so you can call it "Apply" instead of "Verification".
"We don't even know the type of your property" and that is the point, I don't know the type of the field that I like to modify, so I needed a generic way for displaying the appropriate editor field type UI, and you can't assign an "object" type as a value for the SerializedProperty nor get it's value as an "object" type, so here is where I used this guy's extension methods link textl for getting and setting the value of SerializedProperty as "object" type and that did the trick number 2 []~( ̄▽ ̄)~*.
If anyone wished to use my script, feel free to.