Using SerializedProperty on custom classes?

I have tried for a while now to get the SerializedProperty to work on my own custom classes, but have so far been unsuccessful. Basic values works fine(bool, int, string etc), but when I try to get the custom ones the challenge begins. I have tried using the objectReferenceValue on an object that extends ScriptableObject, but this for some reason does not seem to work on multiple objects.

Example: I’ve tried this, and it somehow seems to work with a single object, but only affect one object if multiple is selected.

((MyClass)swipeSound.objectReferenceValue).MyFunction();
((MyClass)swipeSound.objectReferenceValue).myCustomVariable = myCustomVariable;

And would it be possible to convert a SerializedProperty to the actual type without using the ScriptableObject as a base class, something like this:

MyEnum myEnum =((MyEnum)serializedProperty);

I was wondering if anyone have any experience with the SerializedObject/SerializedProperty variables and might have any suggestions to how to overcome these challenges?

To write an editor class that uses SerializableProperty’s to access values from the inspector, the class you’re trying to reference should

  1. Extend ScriptableObject ( which you’ve done)
  2. Have all its variables be individually serializable ( which most unity types are by default and custom classes can be with some work)

It is possible to have a List in a single SerializableProperty though, as long as everything in that List is itself serializable. To build an editor class that is directly associated with a non-editor class, I believe the non-editor class has to be serializable, or at least the variables you are trying to access have to be serializable. Then you can grab a reference to that class using

SerializedObject object; 
OnEnable(){
   object = new SerializedObject(target);  // target is 
}

You may also need

[CustomEditor (typeof(ClassYouAreBuildingAnEditorFor))] at the top of your file (after using declarations but before your main function) - this will open up the target variable used above, which will be a reference to your ClassYouAreBuildingAnEditorFor

To access properties from this class you can use

SerializableProperty prop = object.FindProperty("propertyName");

I think you’ve gotten this far on your own. As for lists, you can use List as long as T is a serializable object. This could be int’s, float, etc or could be a full custom class that is serializable. It’s a bit tricky to access this, but you can use

SerializableProperty list = object.FindProperty("ListOfSerializableObjects");
SerializableProperty listItem = list.GetArrayElementAtIndex(i)) ;

To get or set values of SerializableProperty items, you can use

item.floatValue // for floats
item.objectReferenceValue // for objects

Keep in mind you can iterate serialized lists (they are type IEnumerator) and if you’re using basic arrays theres a number of helper functions you can call from SerializedProperty.

Theres a number of other things to do, as the objects are stored as type SerializableObject not as their original type, but I would recommend watching the Intro to Editor Scripting video from Unite 2011 Linked here as that was helpful for me, and likely more accurate. It’s a little complicated but once you get the hang of which objects are which type and how to access those, its not too bad. Look at the script documentation for SerializableObject and SerializableProperty as well. Best of luck and I hope this helps.

Below is a C# function call for the editor to display child properties of a serialized property.

Usage:

public override void OnInspectorGUI() {

    string propertyName = "speed";
    SerializedProperty sp = serializedObject.FindProperty(propertyName);

    while (sp.Next(true)){
        ShowRelativeProperty(sp, "min");
        ShowRelativeProperty(sp, "max");
    }
}

// Show child property of parent serializedProperty
void ShowRelativeProperty(SerializedProperty serializedProperty, string propertyName)
{
    SerializedProperty property = serializedProperty.FindPropertyRelative(propertyName);
    if (property != null)
    {
        EditorGUI.indentLevel++;
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(property, true);
        if (EditorGUI.EndChangeCheck())
            serializedObject.ApplyModifiedProperties();
        EditorGUIUtility.LookLikeControls();
        EditorGUI.indentLevel--;
    }
}