Unity中的Inspector面板可以顯示的屬性包括以下兩類:
(1)C#以及Unity提供的基礎類型;
(2)自定義類型,並使用[System.Serializable]關鍵字序列化,比如:
[System.Serializable]
public class TestClass { public Vector3 vec = Vector3.zero; public Color clr = Color.green; }
也可以使用[System.NonSerialized]標記不需要顯示的屬性,比如:
public class TestClass
{
[System.NonSerialized]
public Vector3 vec = Vector3.zero; }
有的時候對於U3D默認的Inspector不能滿足需求,則可以對特定類型的Inspector面板進行自定義:編寫一個對應的Editor類,然后重寫其OnInspector方法,比如我們有如下類型:
using UnityEngine;
using System.Collections; [System.Serializable] public class TestClass { public Vector3 vec = Vector3.zero; [System.NonSerialized] public Color clr = Color.green; } [ExecuteInEditMode()] [RequireComponent(typeof(TestComponent))] public class TestInspector : MonoBehaviour { public Vector3 lookAtPoint = Vector3.zero; public Vector3 pos = Vector3.zero; public TestClass testObj = new TestClass(); void Update() { transform.LookAt(lookAtPoint); transform.position = pos; } }
然后在Editor目錄下添加如下腳本:
using UnityEngine;
using UnityEditor; using System.Collections; [CustomEditor(typeof(TestInspector))] public class TestInspectorEditor : Editor { private SerializedObject obj; private SerializedProperty lookAtPoint; private SerializedProperty pos; private SerializedProperty testObj; // 添加TestInspector組件的GameObject被選中時觸發該函數 void OnEnable() { obj = new SerializedObject(target); lookAtPoint = obj.FindProperty("lookAtPoint"); pos = obj.FindProperty("pos"); testObj = obj.FindProperty("testObj"); } // 重寫Inspector檢視面板 public override void OnInspectorGUI() { obj.Update(); EditorGUILayout.PropertyField(lookAtPoint); EditorGUILayout.PropertyField(pos); EditorGUILayout.PropertyField(testObj, true); // 第二個參數表示有子節點需要顯示 obj.ApplyModifiedProperties(); } }
在OnInspector函數中就可以實現你想要的效果。
上面的代碼中有幾點需要注意:
(1)[ExecuteInEditMode()]這個函數可以使代碼在編輯模式下運行,不需要運行游戲;
(2)TestInspectorEditor類必須繼承自Editor,CustomEditor告訴U3D哪個組建類型需要自定義,OnInspectorGUI在顯示組件的Inspector面板時調用;
(3)SerializedObject序列化物體、SerializedProperty序列化屬性和Editor這三者一起使用,用來訪問和更新組件的屬性,SeriailzedProperty能夠以通用的方式訪問所有的基礎類型,包括對數組的控制等;
(4)可以在OnInspectorGUI中調用DrawDefaultInspector函數用來顯示默認的監事面板內容;
(5)EditorGUILayout.PropertyField(testObj, true);如果該類型有子節點,第二個參數需要設置為true才能正確的展開;
(6)[HideInInspector]也可用於隱藏屬性顯示。
******************************************************************************************
除了自定義Inspector檢視面板,我們還可以類似的方法自定義場景視圖中對物體的控制,方法是重定義Editor的OnSceneGUI()函數,比如:
using UnityEngine; using UnityEditor; using System.Collections; [CustomEditor(typeof(TestInspector))] public class TestInspectorEditor : Editor { private SerializedObject obj; private SerializedProperty lookAtPoint; private SerializedProperty pos; private SerializedProperty testObj; // 添加TestInspector組件的GameObject被選中時觸發該函數 void OnEnable() { obj = new SerializedObject(target); lookAtPoint = obj.FindProperty("lookAtPoint"); pos = obj.FindProperty("pos"); testObj = obj.FindProperty("testObj"); } // 重寫Inspector檢視面板 public override void OnInspectorGUI() { obj.Update(); EditorGUILayout.PropertyField(lookAtPoint); EditorGUILayout.PropertyField(pos); EditorGUILayout.PropertyField(testObj, true); // 第二個參數表示有子節點需要顯示 obj.ApplyModifiedProperties(); } void OnSceneGUI() { // 繪制一條由target到世界坐標原點的直線,顏色為黃色 Handles.color = Color.yellow; Handles.DrawLine((target as TestInspector).transform.position, Vector3.zero); // 創建一個位置控制柄 Handles.PositionHandle(Vector3.zero, Quaternion.identity); // 創建一個滑動控制柄,可以沿某個方向滑動target Handles.Slider((target as TestInspector).transform.position, Vector3.zero); (target as TestInspector).transform.position = Handles.FreeMoveHandle((target as TestInspector).transform.position, Quaternion.identity, 2.0f, Vector3.zero, Handles.DrawRectangle); if (GUI.changed) { EditorUtility.SetDirty(target); } } }
主要是使用Handles編輯器類來進行自定義,該類型提供了很多方便的操作接口,比如DrawLine、DrawCube、DrawBezier等。
注意,不能在OnSceneGUI中使用SerializedObject。
這篇帖子寫得很不錯:http://blog.csdn.net/lilanfei/article/details/7680802