關鍵概念
- [CustomEditor typeof(ComponentType)]: 修飾,指定派生自Editor 的類爲 ComponentType 類型的編輯器控制類。
- Editor : 派生改類,爲 object 實現自定義的 Inspector 或 editor 界面。
- Editor.OnInspectorGUI : 覆寫 Inspector 繪製
- GUILayout.Button : 創建按鈕,與 GUI 相比,多了 Layout 功能。
- GUI.enabled : 指定後面的 UI 是否可以交互。
- Object.hideFlag : 位掩碼,控制 Inspect 上 Object 的銷燬,保存,可見性等。
- 組件小齒輪菜單 : [MenuItem(“CONTEXT/Transform/XXX”)]。
- UnityEditor.EditorApplication.delay : 下一幀調用
- Object.DestroyImmediate(Objeect) : 立即刪除一個對象,比如組件。
例子
using System;
using System.Reflection;
using UnityEngine;
using UnityEditor;
/// <summary>
/// 擴展 Camera 組件面板
/// </summary>
[CustomEditor(typeof(Camera))]
public class CameraInspectorExtend : Editor
{
public override void OnInspectorGUI()
{
if(GUILayout.Button("My Button"))
{
Debug.Log("My Buffon");
}
base.OnInspectorGUI();
}
}
/// <summary>
/// 利用反射擴展組件面板
/// Transform 的擴展不是必須用反射,這裏僅是舉例
/// </summary>
[CustomEditor(typeof(Transform))]
public class TransformView : Editor
{
private Editor m_Editor;
private void OnEnable()
{
// 利用反射從dll中拿到編輯面板類型,並創建
Type transEditorType = Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true);
m_Editor = Editor.CreateEditor(target, transEditorType);
}
public override void OnInspectorGUI()
{
if(GUILayout.Button("My Button"))
{
Debug.Log("Click my button");
}
m_Editor.OnInspectorGUI();
//base.OnInspectorGUI();
}
}
/// <summary>
/// 控制組件是否可以編輯
/// </summary>
[CustomEditor(typeof(MyBehaviourScript))]
public class MyBehaviourView : Editor
{
public override void OnInspectorGUI()
{
MyBehaviourScript cmpt = target as MyBehaviourScript;
cmpt.enableEdit = GUILayout.Toggle(cmpt.enableEdit, "可編輯");
// 禁用組件編輯
GUI.enabled = cmpt.enableEdit;
base.OnInspectorGUI();
// 啓用組件編輯
GUI.enabled = true;
// 路徑選擇面板
cmpt.folderGameObject = EditorGUILayout.ObjectField("Folder", cmpt.folderGameObject, typeof(Object));
if(cmpt.folderGameObject)
cmpt.folder = AssetDatabase.GetAssetPath(cmpt.folderGameObject);
}
}
/// <summary>
/// 控制選中對象的可編輯開關
/// </summary>
public class InspectorEditableCtrl
{
[MenuItem("GameObject/3D Object/Lock/Lock", false, 0)]
static void Lock()
{
if(Selection.gameObjects != null)
{
foreach(GameObject go in Selection.gameObjects)
{
go.hideFlags = HideFlags.NotEditable;
}
}
}
[MenuItem("GameObject/3D Object/Lock/Unlock", false, 0)]
static void Unlock()
{
if (Selection.gameObjects != null)
{
foreach (GameObject go in Selection.gameObjects)
{
go.hideFlags = HideFlags.None;
}
}
}
}
/// <summary>
/// 擴展組件 小齒輪 菜單欄
/// CONTEXT 必須用大寫
/// 格式:[MenuItem("CONTEXT/組件類名/XXX")]
/// </summary>
public class InspectorContextExtend
{
/// <summary>
/// 擴展 Transform
/// </summary>
/// <param name="cmd"></param>
[MenuItem("CONTEXT/Transform/My 1")]
static void MyTransfor1(MenuCommand cmd)
{
Debug.Log("Context: " + cmd.context.name);
}
/// <summary>
/// 擴展 MyBehaviourScript
/// </summary>
/// <param name="cmd"></param>
[MenuItem("CONTEXT/MyBehaviourScript/My 1")]
static void MyTransfor2(MenuCommand cmd)
{
Debug.Log("Context: " + cmd.context.name);
}
}
更復雜的繪製例子
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class MyMono1 : MonoBehaviour
{
public enum EType
{
A,
B
}
public Vector2 mScrollPos;
public int mID;
public string mName;
public GameObject mObject;
public EType mEnum;
public bool mToggleA;
public bool mToggleB;
}
#if UNITY_EDITOR
[CustomEditor(typeof(MyMono1))]
public class MyMono1Editor : Editor
{
private bool mEnableToggle;
/// 添加小齒輪菜單
[ContextMenu("Remove Component")]
void RemoveComponent()
{
Debug.Log("Remove " + GetType().ToString());
// 下一幀調用
UnityEditor.EditorApplication.delayCall += ()=>
{
DestroyImmediate(this);
};
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
MyMono1 sc = target as MyMono1;
sc.mScrollPos = EditorGUILayout.BeginScrollView(sc.mScrollPos, false, true);
sc.mName = EditorGUILayout.TextField("Name", sc.mName);
sc.mID = EditorGUILayout.IntField("ID", sc.mID);
sc.mObject = EditorGUILayout.ObjectField("Object", sc.mObject, typeof(GameObject), true) as GameObject;
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("A"))
{
Debug.Log("MyMono click A");
}
if (GUILayout.Button("B"))
{
Debug.Log("MyMono click B");
}
sc.mEnum = (MyMono1.EType)EditorGUILayout.EnumPopup("Enum", sc.mEnum);
EditorGUILayout.EndHorizontal();
mEnableToggle = EditorGUILayout.BeginToggleGroup("toggle", mEnableToggle);
sc.mToggleA = EditorGUILayout.Toggle("A", sc.mToggleA);
sc.mToggleB = EditorGUILayout.Toggle("B", sc.mToggleB);
EditorGUILayout.EndToggleGroup();
EditorGUILayout.EndScrollView();
}
}
#endif