目錄
一、MenuItem --> Unity菜單選項擴展
二、CustomEditor --> 針對自定義Component的Inspector面板的擴展
三、DrawGizmo輔助顯示
四、OnGUI
五、EditorWindow --> 自定義一個窗口
六、ScriptableWizard --> 自定義一個對話框
Unity提供了靈活的插件支持,供開發者自定義插件來提供開發效率,幾乎所有介紹到的支持都必須包含
using UnityEditor;
一般所屬腳本文件需要放在名為Editor的目錄下,如果不想將腳本文件放在Editor下,就需要用預編譯包含相關文件,否則編譯打包時會報錯
#if UNITY_EDITOR //...... Code In Editor #endif
以下簡單介紹幾種常用擴展
* 必須寫在靜態方法之前
* 格式: [MenuItem("路徑", isValidateFunction , 優先級)]
路徑 --> 用"/"分割路徑層級,可支持添加快捷鍵(語法細節不深入)
isValidateFunction --> 是否有驗證函數,比如[MenuItem("Assets\OutputVertexCount", true)],Unity將自動執行一個名為ValidateOutputVertexCount(Validate+菜單選項名)的函數,返回值為true則該菜單項才會被啟用
優先級 --> 指在彈出的菜單中顯示排序的優先級,小前大后(系統自帶選項有自己的優先級數值,這個沒有深究其數值范圍,一般相隔100內的選項會成組,並被用橫線隔開,這個制作插件的時候自由發揮,無需在意太多細節),默認在菜單最后
簡單說就是編輯器中的右鍵菜單擴展,包括以下幾類
1) Assets
[MenuItem("Assets/NPC/生成",false, 1)] public static void GeneratePrefab() { //.......// }
效果如圖:
以及 
2) GameObject
[MenuItem("GameObject/UITemplate/Creat To Prefab", false, 11)] static void CreatToPrefab(MenuCommand menuCommand) { //.......// }
效果類似Assets,不同的是可在Hierarchy層級面板彈出右鍵菜單中看到添加的選項
3) 其他字符串
直接在編輯器上層菜單欄添加
4) Selection
在函數中善用Unity自帶的Selection類,Selection.Objects用來指帶目前被選中的對象(一個或多個),進行邏輯操作。詳細用法參照
二、CustomEditor --> 針對自定義Component的Inspector面板的擴展
在開發中經常遇到自己寫了一個腳本Component,附帶了一些屬性和邏輯,想要自定義這個Component在Inspector面板的一些操作,就要用到CustomEditor擴展
用法很簡單,如下:
//Editor類 --> 下面這句聲明了專門是為MyComponent定制的 [CustomEditor(typeof(MyComponent))] public class MyComponentEditor : Editor { //Inspector面板的顯示繪制 public void OnInspectorGUI() { //........// } //還可以自定義scene視圖的顯示繪制 public void OnSceneGUI() { //........// } } //MyComponent類的實現 public class MyComponent: MonoBehaviour { //......// }
MyComponent是我們自己實現的功能類,當Scene視圖中某個GameObject被選中,且該GameObject有MyComponent這個控件,則其對應的MyComponentEditor就會接管編輯器的顯示,如:
1) OnInspectorGUI --> 控制Inspector面板的繪制
如果需要顯示默認的Inspcetor,則加一句 DrawDefaultInspector() 就行了

繪制GUI主要依靠幾個類:
GUI, GUILayout, EditorGUILayout, EditorGUI 用於繪制按鈕、文字,單選框,滾動條,圖片之類的,GUI與Editor大體是一樣的
GUIStyle 風格設置
建議可以在需要繪制UI的時候去查一下手冊,看看有什么可以用到的控件。
2) OnSceneGUI --> 控制Scene視圖窗口的消息處理
這個函數可以接收Scene視窗中發生的事件 --> UnityEngine.Event
public void OnSceneGUI() { //可獲取當前事件 UnityEngine.Event e = UnityEngine.Event.current; //事件類型(常見有MouseUp/Down, KeyUp/Down, Layout, Used, Repaint等) UnityEngine.EventType EType = e.type; //根據事件類型,在OnSceneGUI做對應的顯示處理 //以下判斷識別鼠標按下,移動,或者拖動 if (EType == UnityEngine.EventType.MouseDown || EType == UnityEngine.EventType.MouseMove || EType == UnityEngine.EventType.MouseDrag) { //Event.current中有詳細的狀態信息 //如下面獲取了某些按鍵的狀態,進行邏輯排除 if (UnityEngine.Event.current.alt //按着alt鍵位 忽略 || UnityEngine.Event.current.button == 2 //中鍵 忽略 ) { return; } //下面代碼在獲取鼠標點擊的位置 Ray worldRay = HandleUtility.GUIPointToWorldRay(UnityEngine.Event.current.mousePosition); RaycastHit hitInfo; if (Physics.Raycast(worldRay, out hitInfo)) { Vector2 Target = new Vector2(hitInfo.point.x, hitInfo.point.z); } } //調用Use()表示該事件已經被處理過了,不會再傳給其他模塊 UnityEngine.Event.current.Use(); }
3) Unity內置控件的Editor
Unity已有的內置空間也可以做Editor擴展,如Material有MaterialEditor,這塊沒嘗試過...
4) Attributes --- 常見屬性標簽語法
我們會常常用到一些標簽式的語法,修飾在某個函數或者類前,用來指代這個函數或者類的一些屬性,MenuItem就是其中一種,常見的還有:
//表現MyCompoent需要用到MeshFilter這個Component,添加MyComponent的時候,如果同級沒有MeshFilter,會自動添加 [RequireComponent(typeof(MeshFilter))] public class MyComponent : MonoBehaviour { } //表示這個Component在Edit模式下也會運行,但注意其Update只有在場景中的GameObject有發生變化的時候才會調用 [ExecuteInEditMode] public class MyComponent: MonoBehaviour{ } public class MyComponent:MonoBehaviour{ //序列化屬性,可在Inspector見到(即使是private),並操作 [SerializeField] private bool hasHealthPotion = true; //不在Inspcetor顯示這個屬性 [HideInInspector] public int p = 5; }
重載MonoBehaviour的OnDrawGizmos可以用來繪制在場景輔助顯示,如Line(線段), Mesh(網格), Ray(射線), Sphere(球形)等。
具體使用Gizmos.DrawXXX系列函數,參考
需注意Scene視圖默認顯示Gizmos繪制,如果要在Game視圖顯示Gizmos,需選中如圖按鈕

項目在調試玩家自動戰斗AI、玩家搖桿移動、布怪、刷阻擋,都用到了Gizmos這個功能,好處是調試起來較為直觀
重載MonoBehaviour的OnGUI可以用來在場景視圖上繪制簡單的UI界面
項目目前使用OnGUI繪制幀率,內存等游戲基本信息
EditorWindow用於創建一個獨立窗口,當你在制作一個功能較雜且較為獨立的插件的時候或許會用到。用法也十分簡單,編寫一個繼承EditorWindow的類就行了
public class ConsoleEditorWindow : EditorWindow {
//重載OnGUI,其繪制的UI不是在Scene視圖中,而是在打開的EditorWindow上
void OnGUI()
{
}
}
繪制的函數也是使用GUILayout,EditorGUILayout等一系列API,不在贅述。
另外你需要通過編寫一個帶MenuItem的Attribute或者其他什么函數,來作為打開這個EditorWindow的入口。
EditorWindow中包含一些比較常用的函數,如:
1) Show ---> 顯示窗口,功能類似的還有ShowPopup,ShowAsDropDown等,不同的是這些接口應用了一些固定的外觀Style
2) Repaint ---> 重繪,你在OnGUI中處理了一些邏輯,需要重繪來理解更新UI的,可以調用這個
3) Close --> 關閉窗口
4) OnFocus/OnLostFocus --> 窗口得到或者失去焦點,也挺有用的
六、ScriptableWizard --> 自定義一個對話框
由ScripttableWizard派生出來的類主要干的事情就是類似你安裝一個軟件時,不停的彈出引導安裝的對話框(下一步取消下一步取消下一步取消下一步取消)的事情一樣。
不過ScripttableWizard目前只支持兩個操作按鈕(Create、Other)
有用到類似功能的朋友可以去看看
結語:
本文主要簡介了下Unity編寫插件的幾種方式,沒有具體講到某個插件例子的編寫。實際編寫遇到的問題大部分是因為對API的不熟悉,只能通過多多Google,查找手冊來一步步完成自己的插件,這是個繁瑣的過程。
希望讀完本文,讀者在拿到一個別人編寫的插件時,也能大體想象出插件的代碼結構,快速找出插件的關鍵代碼,為自己所用。
