Unity ScriptableObject自定義屬性顯示


1. 繼承Editor,重寫OnInspectorGUI方法

Editor官方文檔

需求

將TestClass中intData屬性和stringData按指定格式顯示。

實現

定義一個測試類TestClass,一個可序列化類DataClass

[CreateAssetMenu]
public class TestClass : ScriptableObject
{
    [Range(0, 10)]
    public int intData;
    public string stringData;
    public List<DataClass> dataList;
}
[System.Serializable]
public class DataClass
{
    [Range(0, 100)]
    public int id;
    public Vector3 position;
    public List<int> list;
}

 

//指定類型
[CustomEditor(typeof(TestClass))]
public class TestClassEditor  : Editor
{
    SerializedProperty intField;
    SerializedProperty stringField;
    void OnEnable()
    {
        intField = serializedObject.FindProperty("intData");
        stringField = serializedObject.FindProperty("stringData");
    }
    public override void OnInspectorGUI()
    {
        // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
        serializedObject.Update();
        EditorGUILayout.IntSlider(intField, 0, 100, new GUIContent("initData"));
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(stringField);
        if(GUILayout.Button("Select"))
        {
            stringField.stringValue = EditorUtility.OpenFilePanel("", Application.dataPath, "");
        }
        EditorGUILayout.EndHorizontal();
        // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
        //需要在OnInspectorGUI之前修改屬性,否則無法修改值
        serializedObject.ApplyModifiedProperties();
        base.OnInspectorGUI();
    }
}

Editor嵌套

通過Edtiro.CreateEditor可實現Editor的嵌套。

創建一個類TestClass2,它包含一個TestClass的屬性。

[CreateAssetMenu]
public class TestClass2 : ScriptableObject
{
    public TestClass data;
}

創建一個Test2Class的asset。它的Inspector面板的默認顯示:


它並沒有把TestClass的屬性顯示出來,如果要查看TestClass的屬性,必須雙擊,跳到相應界面,但這樣有看不到TestClass2的屬性。

如果想在Test2Class的Inspector面板中直接看到並且可以修改TestClass的屬性,可以重寫TestClass2的Editor,並在其中嵌套TestClass的Editor。

 1 [CustomEditor(typeof(TestClass2))]
 2 public class TestClass2Editor : Editor
 3 {
 4     Editor cacheEditor;
 5     public override void OnInspectorGUI()
 6     {
 7         // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
 8         serializedObject.Update();
 9         //顯示TestClass2的默認UI
10         base.OnInspectorGUI();
11         GUILayout.Space(20);
12         var data = ( (TestClass2)target ).data;
13         if(data != null)
14         {
15             //創建TestClass的Editor
16             if (cacheEditor == null)
17                 cacheEditor = Editor.CreateEditor(data);
18             GUILayout.Label("this is TestClass2");
19             cacheEditor.OnInspectorGUI();
20         }
21     }
22 }

這樣就可以直接在TestClass2的面板中直接查看和編輯TestClass的屬性。

2. 使用PropertyDrawer

PropertyDrawer官方文檔

如果想修改某種特定類型的顯示,使用繼承Editor的方式就會變得很麻煩,因為所有使用特定類型的asset都需要去實現一個自定義的Editor,效率非常低。這種情況就可以通過繼承PropertyDrawer的方式,對指定類型的屬性,進行統一顯示。

需求

為Inspector面板中的所有string屬性添加一個選擇文件按鈕,選中文件的路徑直接賦值給該變量。

實現

 1 [CustomPropertyDrawer(typeof(string))]
 2 public class StringPropertyDrawer : PropertyDrawer
 3 {
 4     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 5     {
 6         Rect btnRect = new Rect(position);
 7         position.width -= 60;
 8         btnRect.x += btnRect.width - 60;
 9         btnRect.width = 60;
10         EditorGUI.BeginProperty(position, label, property);
11         EditorGUI.PropertyField(position, property, true);
12         if (GUI.Button(btnRect, "select"))
13         {
14             string path = property.stringValue;
15             string selectStr = EditorUtility.OpenFilePanel("選擇文件", path, "");
16             if (!string.IsNullOrEmpty(selectStr))
17             {
18                 property.stringValue = selectStr;
19             }
20         }
21         EditorGUI.EndProperty();
22     }
23 }

加了一個PropertyDrawer之后,Inspector面板中的所有string變量都會額外添加一個Select按鈕。

注意事項

  1. PropertyDrawer只對可序列化的類有效,非可序列化的類沒法在Inspector面板中顯示。
  2. OnGUI方法里只能使用GUI相關方法,不能使用Layout相關方法。
  3. PropertyDrawer對應類型的所有屬性的顯示方式都會修改,例如創建一個帶string屬性的MonoBehaviour:

3. 使用PropertyAttribute

PropertyAttribute官方文檔

如果想要修改部分類的指定類型的屬性的顯示,直接使用PropertyDrawer就無法滿足條件,這時可以結合PropertyAttribute和PropertyAttribute來實現需求。

需求

為部分指定類的int或float屬性的顯示添加滑動條,滑動條的上下限可根據類和屬性自行設置。

實現

 

 1 public class RangeAttribute : PropertyAttribute
 2 {
 3     public float min;
 4     public float max;
 5     public RangeAttribute(float min, float max)
 6     {
 7         this.min = min;
 8         this.max = max;
 9     }
10 }
11 [CustomPropertyDrawer(typeof(RangeAttribute))]
12 public class RangeDrawer : PropertyDrawer
13 {
14     // Draw the property inside the given rect
15     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
16     {
17         // First get the attribute since it contains the range for the slider
18         RangeAttribute range = attribute as RangeAttribute;
19         // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer.
20         if (property.propertyType == SerializedPropertyType.Float)
21             EditorGUI.Slider(position, property, range.min, range.max, label);
22         else if (property.propertyType == SerializedPropertyType.Integer)
23             EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max, label);
24         else
25             EditorGUI.LabelField(position, label.text, "Use Range with float or int.");
26     }
27 }

修改TestClass和DataClass

 1 [CreateAssetMenu]
 2 public class TestClass : ScriptableObject
 3 {
 4     [Range(0, 10)]
 5     public int intData;
 6     public string stringData;
 7     public List<DataClass> dataList;
 8 }
 9 [System.Serializable]
10 public class DataClass
11 {
12     [Range(0, 100)]
13     public int id;
14     public Vector3 position;
15     public List<int> list;
16 }

其他

  • 需要修改顯示的類都需要滿足Unity的序列化規則
  • 這幾種顯示方式對Serializable Class都可以使用,並不需要一定是ScriptableObject。只是在編輯器下,ScriptableObject來保存臨時數據比較常用,所以使用ScriptableObject來做例子。

轉載請注明出處:http://www.cnblogs.com/chiguozi/p/6873050.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM