Creating Editor for SerializedProperty

Is there a way to create and editor for a serialized property?

So far, there’s no such option on Editor.CreateEditor (…) overloads, so I was wondering how to achieve it when I have no info on the object that represents the serialized property (not the serialized object that contains it).

You can create a custom property drawer for it. Then you can use EditorGUI.PropertyField(your serialized property) without having to know the type of your serialized property.

The exception is if the property points to an object reference and you want to draw a custom editor for that object reference. For example, say you have this class:

public class MyBehaviour : MonoBehaviour {
    public ScriptableObject so;
}

and you’ve defined subclasses of ScriptableObject such as:

[CreateAssetMenu]
public GameData : ScriptableObject {
    public string aString;
}

with a custom editor:

[CustomEditor(typeof(GameData), true)] // 'true' to also apply editor to subclasses.
public class GameDataEditor : Editor {
    public override OnInspectorGUI() {
        serializedObject.Update();
        EditorGUILayout.LabelField("Game Data:");
        EditorGUILayout.PropertyField(serializedObject.FindProperty("aString"));
        serializedObject.ApplyModifiedProperties();
    }
}

Then your custom editor for MyBehaviour can create an editor for its “so” without having to know the type ahead of time:

public class MyBehaviourEditor : Editor {

    private Editor m_editor;

    void OnEnable() {
        var editor = Editor.CreateEditor(serializedObject.FindProperty("so").objectReferenceValue);
    }

    public override voice OnInspectorGUI() {
        editor.OnInspectorGUI();
    }
}

I’m not sure if this is what you’re asking, but I hope it helps.

Thanks @TonyLi for the explanation. Does EditorGUILayout.PropertyField(…) also work for missing scripts? I mean, when a component in the component list of a game object / user prefab returns null but I get the corresponding serialized property with something like:

var serializedComponents = serializedObject.FindProperty ( "m_Component" );
...
var serializedProperty = serializedComponents.GetArrayElementAtIndex ( i );

Remember that “serializedProperty” corresponds to a missing script (which as component is null).

And the answer to my question regarding EditorGUILayout.PropertyField(…) for missing scripts is “No”: it returns a null editor and throws the following exception message: “type is not a supported pptr value”.

Any workaround?

Try this:

for (int i = 0; i < serializedComponents.arraySize; i++) {
    var serializedProperty = serializedComponents.GetArrayElementAtIndex( i );
    if (serializedProperty.FindPropertyRelative("second").objectReferenceValue == null) continue; // Skip null.
    //...your regular code...
}

Actually I need to work with the “lost” reference to the missing script which is null in order to create a custom editor for it (for MonoBehaviour type). I don’t know how Unity accomplish to get a general editor to deal with this out of null objectReferenceValue.

Wow, if I understand you correctly, that’s really obscure. You want to provide an editor for the serialized data that a GameObject or prefab still has for a missing script, right? If so, then as you’ve already remarked I don’t think you can use Editor.CreateEditor. But you could go by the fileID to determine how to draw the properties and/or iterate over them using SerializedProperty.Next, passing each one to EditorGUI.PropertyField.

that’s really obscure.

Indeed. It’s what Unity’s editor does when a missing script is found and assigns a GenericEditor somehow with a non-null serializedObject.

When there’s a missing script, doesn’t it just show a warning help box?

might be little off topic:

i think Unity Editor saves the serialized data, in this case the MonoBehaviour’s serializable’s, to the Scene_*.unity file. If you deleted a script, creating a new c# won’t remedy it. You might have to dig up a backup version and copy over the .cs and .meta from File Explorer, to get rid of those Missing Mono Script message(s).

Lesson is, Don’t Delete the existing one thats in your Assets folder, if you’re just going to replace it with an Updated version, and you wont have to worry about this issue.

@TonyLi : I know, but this is for my own editor extension.

@Izzy2000 : you can remove the offending component by code, but it has 2 flaws: (1) it does not create an Undo entry, and (2) even if you save the scene, Unity’s editor still watches the script “in the shadows” and so the only way to make sure is really deleted is by closing and reopening Unity’s editor.

Right, so in that case you’ll have to go by “fileID” or just iterate over the properties using SerializedProperty.Next.

Yes, but the thing is that the "“m_LocalIdentfierInFile” value is only available on the SerializedObject. And SerializedProperty.Next does not take me to a property linked to the missing script.

Sorry, no ideas. I hope you’ll post the solution here when you find it, in case it can help others in the future.

Sure do, … if I eventually find it. Thanks for your help, anyways.

@TonyLi : so far, this is a deadend.

It seems this is all handled from the unmanaged side of Unity3d.

So far, all I have achieved is getting the property “second” from the missing behaviour. Then, with the help of EditorGUILayout.PropertyField select a script file and then assign the corresponding behaviour as a new component (since as we all know, direct instantiation of components with “new” is not allowed).

But this approach has two problems: (1) even if you apply modifications and save the scenes and project, unless you close and re-open Unity, the missing script seems to be there (as if all modifications were disregarded), and (2) I have found no way to copy the serialized data of the missing script into the newly created one (since I don’t know which property or set of properties hold those values), so the added behaviour is created with default values.

So, as said at the begining of this post, this is kinda dead end.

Sounds like it. It’s probably safer anyway. Since it’s well beyond the public API, Unity could change it whenever they want.

On the bright side, the latest version of my plugin has been released on the Asset Store.

1 Like

Looks good! Drag to reorder would be a nice addition. I always find it awkward to have to repeatedly click and then select Move Up or Move Down.

1 Like

Thanks. Added to the roadmap.

I’m close to find a solution, all I need is to know which property holds the set of key/value pairs for each field serialized for the missing script component. Any clues?