Unity3D編輯器外掛編寫教程

xy849288321發表於2013-01-29


在閱讀本教程之前,你需要對Unity的操作流程有一些基礎的認識,並且最好了解內建的GUI系統如何使用。
如何讓編輯器執行你的程式碼

Unity3D可以通過事件觸發來執行你的編輯器程式碼,但是我們需要一些編譯器引數來告知編譯器何時需要觸發該段程式碼。

[MenuItem(XXX)]宣告在一個函式上方,告知編譯器給Unity3D編輯器新增一個選單項,並且當點選該選單項的時候呼叫該函式。觸發函式裡可以編寫任何合法的程式碼,可以是一個資源批處理程式,也可以彈出一個編輯器視窗。程式碼裡可以訪問到當前選中的內容(通過Selection類),並據此來確定顯示檢視。與此類似,[ContextMenu("XXX")]可以向你的上下文選單中新增一個選單項。

當你編寫了一些Component指令碼,當它被附屬到某個GameObject時,想在編輯檢視即可在Scene檢視觀察到效果,那麼你可以把[ExecuteInEditMode]寫在類上方來通知編譯器,該類的OnGUI和Update等函式在編輯模式也也會被呼叫。我們還可以使用[AddComponentMenu("XXX/XXX")]來把該指令碼關聯到Component選單中,點選相應選單項即可為GameObject新增該Component指令碼。
開始編寫編輯器

為了避免不必要的包含,Unity3D的執行時和編輯器類分辨儲存在不同的Assemblies裡(UnityEngine和UnityEditor)。當你準備開始編寫編輯器之前,你需要using UnityEditor來匯入編輯器的名稱空間。

有些程式碼可能是執行時和編輯器都需要執行的,如果你想在其中加以區分,那麼可以使用#if UNITY_EDITOR ... #endif巨集來對編輯器程式碼做特殊處理。

在你開始真正編寫程式碼之前,我認為你還需要知道所有放在命名為Editor目錄下的指令碼會在其它指令碼之後進行編譯,這方便了你去使用那些執行時的內容。而那些目錄下的指令碼是不能訪問到Editor目錄下的內容的。所以,你最好把你的編輯器指令碼寫在Editor目錄下。
如何建立自定義編輯器視窗
建立你的視窗

如果你想自定義一個可編輯的皮膚,那麼你需要編寫一個繼承自EditorWIndow的類。通常情況下,你還需要寫一個[MenuItem]來告知編譯器何時開啟這個皮膚。這個事件的回撥應該是一個靜態方法,並且返回一個視窗的例項。

現在,當你點選對應的選單項時,會彈出一個空白的視窗。並且你可以像Unity3D編輯器預製的視窗一樣隨意拖動和停靠。下面來看看我們如何來在視窗內實現我們想要的功能吧。
擴充套件你的視窗

和執行時的GUI一樣,如果你需要在視窗中新增互動控制元件,那麼必須重寫OnGUI方法。具體的重寫方式和執行時的GUI一樣,你甚至可以使用任何擴充套件自原生GUI系統的外掛(例如iGUI和GUIX)來簡化你的外掛開發流程(僅經過初步測試,更深層次的可用性尚待驗證)。同時UnityEditor名稱空間下的EditorGUILayout在原生GUI之上提供了一些更方便的介面和控制元件,讓你可以輕鬆的使用一些編輯器特有的UI控制元件。

除了OnGUI外,你可能還會需要如下一些回撥來觸發某些具體的邏輯(完整的列表請參考官方文件):

l OnSelectionChange,但你點選物品時觸發

l OnFocus /OnLostFocus,獲得和失去焦點時觸發
進一步擴充套件你的視窗
自定義控制元件

和執行時GUI的使用方式一樣,如果你打算自定義自己的控制元件,那麼最簡單的方式就是實現一個靜態方法(也可以不是靜態的),並提供一些可選引數,在方法內部根據這些引數來完成對控制元件的佈局(就像你在OnGUI中做的一樣)。

如果你打算把自定義控制元件實現在視窗類內部,你可以使用Partial類來更好的管理你的程式碼。
繪製2D內容
繪製圖片

可以使用GUI.DrawTexture來完成對圖片資源的繪製。
繪製基礎圖元

GUI本身並沒有提供繪製基礎圖元的方法,但是可以通過一些方式來封裝出這些方法。

l 繪製線段:通過一個畫素的貼圖資源配合GUI.DrawTexture和矩陣旋轉來完成線段的繪製。

l 繪製矩形框:通過GUI.Box和樣式設定來封裝出對矩形框和矩形填充框。
資源選擇器

EditorLayout.ObjectField控制元件提供一個資源選擇邏輯,生成時需要指定某種資源型別。然後你可以拖動該種資源到該控制元件或點選控制元件旁邊的小圓圈進行列表進行選擇。
如何儲存編輯內容

你可能需要建立一個繼承自SerializedObject的類來儲存編輯的資料。繼承自SerializedObject的物件能用於儲存資料而不參與渲染,並可以最終打包到AssetBundle。

針對當前的編輯選項等內容的儲存,可能需要另外一個SerializedObject類(和具體的系統設計相關)。
嚮導式的編輯視窗

在很多情況下可能你都會需要一個有很多引數的編輯皮膚,然後在編輯結束後有一個按鈕加以確認。這你不用自己來實現,UnityEditor提供了ScriptableWizard來幫助你快捷的進行開發。

他是繼承自EditorWindow的,所以他們的使用是很類似的。不過注意,當你點選確認按鈕時,OnWizardCreate()會被呼叫。另外,ScriptableWizard.DisplayWizard可以幫助你生成並顯示出該視窗。
如何擴充套件Inspector皮膚

當你在Unity3D中點選一個物件時,Inspector皮膚會隨即顯示出此物件的屬性。我們可以針對某個型別的物件擴充套件該皮膚,這在為Unity3D開發外掛時是非常有用的。
定義INSPECTOR何時被觸發

自定義的Inspector皮膚需要繼承Editor類。由於功能相對具體,所以你無需定義程式碼何時被觸發,對應程式碼會在你點選它所對應的物體時自動執行。

那麼如何定義它所對應的型別呢?只需要在你的類定義之前通過編譯器的命令[CustomEditor(typeof(XXX))]就可以完成這項工作了。
訪問被編輯的物件

在Inspector檢視中,我們經常需要訪問正在被編輯的物件。Editor類的成員變數target正是提供了這一關聯。

儘管如此,需要注意target是一個Object型別的物件,具體使用時可能需要型別轉換(可以使用C#的泛型來避免重複的型別轉換)。
實現你自己的Inspector介面

擴充套件Editor與擴充套件EditorWindow唯一的不同在於你需要重寫的是OnInspectorGUI而不是OnGUI。另外,如果你想繪製預設的可編輯項,只需呼叫DrawDefaultInspector即可。
在Scene介面定義編輯控制程式碼

當選中一個物體的時候,可能我們希望在Scene檢視裡也能定義一些編輯或展現。這一工作可以通過OnSceneGUI和Handle類來完成。OnSceneGUI用來處理來自Scene檢視的事件,而Handle類用來在Scene檢視實現一些3D的GUI控制元件(例如控制物件位置的Position控制器)。

具體的使用方式可以參考官方的參考文件。
一些常用的功能說明

l AssetDatabase.CreateAsset可以幫住你從資源目錄中建立一個資源例項。

l Selection.activeObject返回當前選中的物件。

l EditorGUIUtility.PingObject用來實現在Project視窗中點選某一項的操作。

l Editor.Repaint用來重繪介面所有的控制元件。

l XXXImporter用來設定某種資源的具體匯入設定(例如在某些情況下你需要設定匯入的貼圖為可讀的)。

l EditorUtility.UnloadUnusedAssets用於釋放沒有使用的資源,避免你的外掛產生記憶體洩漏。

l Event.Use用來標記事件已經被處理結束了。

l EditorUtility.SetDirty用來通知編輯器資料已被修改,這樣在下次儲存時新的資料將被儲存。


本文來自:http://www.cnblogs.com/oldman/articles/2407962.html

相關文章