Unity の SerializedObject のメモ。

PropertyDrawers have two uses:
- Customize the GUI of every instance of a Serializable class.
- Customize the GUI of script members with custom PropertyAttributes.

できることは2つ。
Serializeable classのPropertyDrawerを定義する。
PropertyAttributeを定義して既存のSerializable classのPropertyDrawerを差し替える。
Not Serializableなclassに対してPropertyDrawerを定義することはできぬ(TimeSpanとかね)。
PropertyDrawerを定義してみる
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class SampleAttribute : PropertyAttribute
{
}

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(SampleAttribute))]
public class SampleDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var sampleAttribute = (SampleAttribute)attribute;
        Debug.Log(property);
        EditorGUI.PropertyField(position, property, new GUIContent("Hoge"));
    }
}
#endif

public class SampleBehaviour : MonoBehaviour
{
    [Sample]
    public int Value;
}

property.Path
(x:14.00, y:154.00, width:266.00, height:16.00) path: Value

OnGUIでデバッグプリント
        Debug.LogFormat("{0} path: {1}", position, property.propertyPath);

なるほど。次のプロパティではどうか。
    [Sample]
    public List<int> ValueArray;

    [Sample]
    public List<int> ValueList;

OnGUIが呼ばれぬ。プリミティブ型以外はだめなのか?
かと思いきや中身に対して呼ばれることが分かった。
配列、Listの中身に対してPropertyDrawerが呼ばれる。
(x:14.00, y:208.00, width:258.00, height:16.00) path: ValueArray.Array.data[0]
(x:14.00, y:262.00, width:258.00, height:16.00) path: ValueList.Array.data[0]

Serializable class
public enum IngredientUnit { Spoon, Cup, Bowl, Piece }

// Custom serializable class
[Serializable]
public class Ingredient
{
    [Sample]
    public string name;

    [Sample]
    public int amount = 1;

    [Sample]
    public IngredientUnit unit;
}

    public Ingredient ingredient;

    public List<Ingredient> ingredientList;

(x:14.00, y:298.00, width:258.00, height:16.00) path: ingredient.name
(x:14.00, y:406.00, width:258.00, height:16.00) path: ingredientList.Array.data[0].name

CustomEditor
デフォルトと同じ挙動。DrawDefaultInspector()の前後にボタンを追加したりできる。
[CustomEditor(typeof(SampleBehaviour))]
public class ObjectGeneratorEditor : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
    }
}

SerializedObjectのPropertyを列挙してみる
    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        var it = serializedObject.GetIterator();
        bool hasNext = it.NextVisible(true);
        while(hasNext)
        {
            //Debug.Log(it.propertyPath);
            var expand = EditorGUILayout.PropertyField(it, false);
            hasNext=it.NextVisible(expand);
        }

        serializedObject.ApplyModifiedProperties();
    }


EditorGUIの関数はpositionが必要
EditorGUILayoutはposition無用。