<small>前幾天開始準備看源碼,結合自己工作使用Lua,想看sLua框架源碼,但是Lua確實不太熟悉,于是還是選擇C#,打算看NGUI的源碼(因為工作中也有用到)。
自己看源碼經驗不是很多,有些感覺無從下手,因為里面的代碼跳轉太多了,打算先看看NGUI的編輯器是怎么做出來的,于是開始研究Unity的編輯器制作。</small>
一、引言
Unity允許開發者自己制定編輯器,這也給了我們很多的方便,例如:要打包AssetBundle的時候,我們可以自己寫一個菜單項點擊進行我們所想要的打包。還有一些時候我們可以創建一個窗口完成Unity并沒有提供支持的編輯。
二、UnityEditor相關類
- Editor:編輯器
- EditorWindow :編輯窗口(類似Console就是一個編輯窗口),其中初始化方法應為static,否則在Unity編輯過程中不能找到匹配的選項
- GenericMenu :編輯窗口中菜單
- EditorGUILayout :編輯窗口中的界面布局類
- MenuItem屬性:添加菜單項在控制面板主菜單和檢視面板上下文菜單
- GUILayout : 可以在編輯窗口用
- MenuCommand :用于提取上下文菜單項。MenuCommand對象被傳遞給自定義菜單項功能使用菜單項定義的屬性。
- Event : 事件,Event.current.可以獲取到當前的系統處理的事件
<strong>注:編輯器腳本需要放在Editor文件夾下,在進行Unity編輯的時候生效,Unity會把Editor下的腳本認為是Editor腳本,不允許掛載在游戲物體上。</strong>
三、制作菜單
3.1創建主菜單下的菜單項(MenuItem)
終于到了令人期待的動手時刻啦,現來個簡單的
/*
* static void MenuItem (itemName : string, isValidateFunction : bool, priority : int) : MenuItem
* itemName : 菜單名,以"/"分級,第一個是和主菜單同級的位置,該級菜單不能以中文命名,后面的都可以用中文
* isValidateFunction : 這個參數標志是否是驗證函數
* priority : 優先級,值越小,在菜單中越靠上
*/
//主菜單下的一級菜單menu1
[MenuItem("Menu/menu1" , false, 1)]
static public void Menu1()
{
Debug.Log("menu1");
}
//主菜單下的二級菜單menu2
[MenuItem("Menu/menu2/menu2", false, 2)]
static public void Menu2()
{
Debug.Log("menu2/menu2");
}
<strong>在寫編輯器腳本的時候記得要using UnityEditor</strong>
3.2 特定情況下可以使用的菜單
弄完上面這菜單,只有一句話可以說:“這也真是夠爛的”。不過畢竟是最簡單的菜單,接下來,我們慢慢優化,學習嘛,總有個循序漸進的過程。
下面,我們來給菜單添加一個特定情況下使用的功能,例如,我們讓它只在我們選中了某種特定游戲物體的時候才讓他顯示,讓它可以被點擊。
//主菜單下的一級菜單menu1
[MenuItem("Menu/menu1" , false, 1)]
static public void Menu1()
{
Debug.Log("menu1");
}
//這是Menu/menu1的驗證函數,當返回true時,menu1顯示可點,否則不能點
[MenuItem("Menu/menu1", true)]
[MenuItem("Menu/menu1", true)]
static public bool ShowMenu1()
{
GameObject selectObj = Selection.activeGameObject;
return selectObj != null && selectObj.tag == "Display";
}
3.3 給自定義MenuItem綁定快捷鍵
老感覺MenuItem就前面這一點東西不好用,還是有快捷鍵的好,方便多了。
這可能是學習MenuItem最簡單的一個步驟了,一行代碼都不需要,只需要幾個字符,我剛找到方法的時候都不敢相信!!!
解釋和代碼都在下面了:
//主菜單下的二級菜單menu2
/*
* _%H 表示快捷鍵為ctrl + H
* 創建快捷鍵方式 : 在對應的MenuItem后面以" _"開頭,后面添加快捷鍵標志
* 快捷鍵標志規則 :
* % = ctrl
* # = Shift
* & = Alt
* F1…F2 = F...
* LEFT/RIGHT/UP/DOWN = 上下左右
* HOME, END, PGUP, PGDN = 鍵盤上的特殊功能鍵
*/
[MenuItem("Menu/menu2/menu2 _%H", false, 2)]
static public void Menu2()
{
Debug.Log("menu2/menu2");
}
3.4 添加MenuItem到對應Insecptor面板
/*
* 在Inspector中對應的組件中右鍵中添加菜單
* MenuItem("CONTEXT/[ComponentName]/[DisplayName]")
* static void FunctionName(MenuCommand command) { //function body code }
*/
[MenuItem("CONTEXT/Camera/Item")]
static public void Item(MenuCommand command)
{
//command.context獲取對應Object
Camera camera = command.context as Camera;
Debug.Log(string.Format("light info : name = {0}", camera.name));
}
四、創建編輯窗口
前面了解了編輯菜單的制作,現在,我們來學習下編輯窗口怎么做。
其實,一個編輯窗口就是一個EditorWindow,翻譯過來也就是編輯窗口啦。
首先,創建一個腳本,繼承EditorWindow,也就是創建了一個編輯窗口了,只不過沒有顯示罷了。
<strong>再次聲明:我們這些腳本都是放在Editor文件夾下的,我們的腳本也都是繼using UnityEditor才能有效編譯的。</strong>
using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEngine.Tizen;
public class EditWindow : EditorWindow
{
static string myString = "Hello World";
bool groupEnabled;
bool myBool = true;
float myFloat = 1.23f;
static GenericMenu menu;
//初始化,也就是一個MenuItem,當點擊時調用Init()
[MenuItem("Window/EditWindow _%&#B")]
static void Init()
{
Debug.Log("init");
// Get existing open window or if none, make a new one:
GetWindow(typeof(EditWindow)); //獲取到窗口,并且顯示
//實例化并且設置menu
menu = new GenericMenu(); //初始化menu,但是沒有顯示
menu.AddItem(new GUIContent("MenuItem1"), false, Callback, "item 1");
menu.AddItem(new GUIContent("MenuItem2"), false, Callback, "item 2");
menu.AddSeparator("");
menu.AddItem(new GUIContent("SubMenu/MenuItem3"), false, Callback, "item 3");
}
//通過GUI渲染,每幀調用
void OnGUI()
{
//創建要顯示在編輯窗口的內容
GUILayout.Label("Base Settings", EditorStyles.boldLabel);
myString = EditorGUILayout.TextField("Text Field", myString);
EditorGUILayout.Space(); //空行:間隙
//ToggleGroup
groupEnabled = EditorGUILayout.BeginToggleGroup("Optional Settings", groupEnabled);
myBool = EditorGUILayout.Toggle("Toggle", myBool);
myFloat = EditorGUILayout.Slider("Slider", myFloat, -3, 3);
myString = EditorGUILayout.TextField("Field", myString);
EditorGUILayout.EndToggleGroup();
EditorGUILayout.BeginVertical("Button");
GUILayout.Label("I'm inside the button");
GUILayout.Label("So am I");
EditorGUILayout.EndVertical();
Event currentEvent = Event.current;
Rect contextRect = new Rect(0, 200, 100, 100);
//EditorGUI.DrawRect(contextRect, Color.green);
EditorGUI.LabelField(contextRect, "Hello World Text");
if (currentEvent.type == EventType.MouseDown) //點擊事件發生在當前EditorWindow上
{
Vector2 mousePos = currentEvent.mousePosition;
if (contextRect.Contains(mousePos)) //點在矩形范圍內
{
menu.ShowAsContext(); //顯示menu
currentEvent.Use();
}
}
}
//回調
static void Callback(object obj)
{
Debug.Log("Selected: " + obj.ToString());
}
}
這就是創建一個面板的代碼了,可以直接復制到自己的工程中,創建如下窗口
對于里面的OnGUI代碼,就是用到UnityEditor相關類中的一些類了,大家可以研究下。
<strong>最后,文章就到這了,文筆有限,望大家見諒。
歡迎各路英雄互相討論學習。</strong>