うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】SerializedProperty を用いたクラス描画手法 ~2~

だいぶ複雑になるが EditorGUILayout.PropertyFieldincludeChildren: true を利用せずに
すべての SerializedProperty を取得し描画していくこともできる。

NextVisible を利用するのは変わらないが、SerializedPropertyType.Generic の場合は中身を更にループさせている
SerializedPropertyType.Generic の場合でも CustomPropertyDrawer を利用している場合は、適切なUIを表示させるために PropertyField を利用する。

用途

この処理は、自作Attributeを利用しているときに用いる
serializeobject のフィールドのみに Attribute を適応するのであればこちらを利用する必要はないが
フィールドのクラスのも適応させたい場合こちらの処理を利用する必要がある。

コード

SerializedProperty が CustomPropertyDrawer を持っているかどうかの
HasCustomPropertyDrawer はこちらの記事を参考にしてください
hacchi-man.hatenablog.com

private void DrawProperty(SerializedProperty property, bool isSkip = false)
{
    var depth = -1;
    var iterator = property.Copy();
    for (var enterChildren = true; iterator.NextVisible(enterChildren) || depth == -1; enterChildren = false)
    {
        if (depth != -1 && iterator.depth != depth)
            return;

        depth = iterator.depth;
        if (isSkip)
            continue;
        
        if ("m_Script" == iterator.propertyPath)
        {
            using (new EditorGUI.DisabledScope(true))
                EditorGUILayout.PropertyField(iterator);
            continue;
        }
        
        if (iterator.propertyType != SerializedPropertyType.Generic)
        {
            EditorGUILayout.PropertyField(iterator);
            continue;
        }
        
        if (HasCustomPropertyDrawer(iterator))
        {
            EditorGUILayout.PropertyField(iterator, true);
            continue;
        }
        
        EditorGUILayout.PropertyField(iterator, false);
        if (!iterator.isExpanded)
            continue;

        EditorGUI.indentLevel++;
        bool enabled = GUI.enabled;
        var indentLevel = EditorGUI.indentLevel;
        var num = indentLevel - iterator.depth;
        
        EditorGUI.indentLevel = iterator.depth + num;
        DrawProperty(iterator);
        
        GUI.enabled = enabled;
        EditorGUI.indentLevel = indentLevel;
    }
}