Unity 編輯器(UnityEditor)

<small>前幾天開始準(zhǔn)備看源碼,結(jié)合自己工作使用Lua反肋,想看sLua框架源碼踏施,但是Lua確實(shí)不太熟悉,于是還是選擇C#养距,打算看NGUI的源碼(因?yàn)楣ぷ髦幸灿杏玫剑?br> 自己看源碼經(jīng)驗(yàn)不是很多日熬,有些感覺無從下手,因?yàn)槔锩娴拇a跳轉(zhuǎn)太多了耘纱,打算先看看NGUI的編輯器是怎么做出來的毕荐,于是開始研究Unity的編輯器制作东跪。</small>

一、引言

Unity允許開發(fā)者自己制定編輯器虽填,這也給了我們很多的方便斋日,例如:要打包AssetBundle的時(shí)候墓陈,我們可以自己寫一個(gè)菜單項(xiàng)點(diǎn)擊進(jìn)行我們所想要的打包。還有一些時(shí)候我們可以創(chuàng)建一個(gè)窗口完成Unity并沒有提供支持的編輯兔港。

二仔拟、UnityEditor相關(guān)類
  • Editor:編輯器
  • EditorWindow :編輯窗口(類似Console就是一個(gè)編輯窗口),其中初始化方法應(yīng)為static科侈,否則在Unity編輯過程中不能找到匹配的選項(xiàng)
  • GenericMenu :編輯窗口中菜單
  • EditorGUILayout :編輯窗口中的界面布局類
  • MenuItem屬性:添加菜單項(xiàng)在控制面板主菜單和檢視面板上下文菜單
  • GUILayout : 可以在編輯窗口用
  • MenuCommand :用于提取上下文菜單項(xiàng)。MenuCommand對象被傳遞給自定義菜單項(xiàng)功能使用菜單項(xiàng)定義的屬性蔫慧。
  • Event : 事件,Event.current.可以獲取到當(dāng)前的系統(tǒng)處理的事件
    <strong>注:編輯器腳本需要放在Editor文件夾下权薯,在進(jìn)行Unity編輯的時(shí)候生效,Unity會把Editor下的腳本認(rèn)為是Editor腳本盟蚣,不允許掛載在游戲物體上。</strong>

三刁俭、制作菜單

3.1創(chuàng)建主菜單下的菜單項(xiàng)(MenuItem)

終于到了令人期待的動手時(shí)刻啦牍戚,現(xiàn)來個(gè)簡單的


主菜單下的編輯菜單
    /*
     * static void MenuItem (itemName : string, isValidateFunction : bool,  priority : int) : MenuItem
     * itemName : 菜單名如孝,以"/"分級,第一個(gè)是和主菜單同級的位置第晰,該級菜單不能以中文命名,后面的都可以用中文
     * isValidateFunction : 這個(gè)參數(shù)標(biāo)志是否是驗(yàn)證函數(shù)
     * priority : 優(yōu)先級品抽,值越小甜熔,在菜單中越靠上
     */

    //主菜單下的一級菜單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>在寫編輯器腳本的時(shí)候記得要using UnityEditor</strong>

3.2 特定情況下可以使用的菜單

弄完上面這菜單腔稀,只有一句話可以說:“這也真是夠爛的”。不過畢竟是最簡單的菜單淡喜,接下來诵闭,我們慢慢優(yōu)化,學(xué)習(xí)嘛们镜,總有個(gè)循序漸進(jìn)的過程。
下面颈抚,我們來給菜單添加一個(gè)特定情況下使用的功能嚼鹉,例如,我們讓它只在我們選中了某種特定游戲物體的時(shí)候才讓他顯示匹舞,讓它可以被點(diǎn)擊线脚。

不能點(diǎn)擊
//主菜單下的一級菜單menu1
    [MenuItem("Menu/menu1" , false, 1)]
    static public void Menu1()
    {
        Debug.Log("menu1");
    }

    //這是Menu/menu1的驗(yàn)證函數(shù)浑侥,當(dāng)返回true時(shí),menu1顯示可點(diǎn)括丁,否則不能點(diǎn)
    [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就前面這一點(diǎn)東西不好用伶选,還是有快捷鍵的好,方便多了构资。
這可能是學(xué)習(xí)MenuItem最簡單的一個(gè)步驟了肖卧,一行代碼都不需要,只需要幾個(gè)字符,我剛找到方法的時(shí)候都不敢相信?选>湫!

綁定快捷鍵

解釋和代碼都在下面了:

    //主菜單下的二級菜單menu2
    /*
     * _%H 表示快捷鍵為ctrl + H
     * 創(chuàng)建快捷鍵方式 : 在對應(yīng)的MenuItem后面以" _"開頭削咆,后面添加快捷鍵標(biāo)志
     * 快捷鍵標(biāo)志規(guī)則 : 
     *      % = 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到對應(yīng)Insecptor面板
Insecptor中的Camera上添加菜單
    /*
     * 在Inspector中對應(yīng)的組件中右鍵中添加菜單
     * MenuItem("CONTEXT/[ComponentName]/[DisplayName]")
     * static void FunctionName(MenuCommand command) { //function body code }
     */
    [MenuItem("CONTEXT/Camera/Item")]
    static public void Item(MenuCommand command)
    {
        //command.context獲取對應(yīng)Object
        Camera camera = command.context as Camera;
        Debug.Log(string.Format("light info : name = {0}", camera.name));
    }

四鳞陨、創(chuàng)建編輯窗口

前面了解了編輯菜單的制作瞻惋,現(xiàn)在,我們來學(xué)習(xí)下編輯窗口怎么做掏导。
其實(shí)羽峰,一個(gè)編輯窗口就是一個(gè)EditorWindow,翻譯過來也就是編輯窗口啦值纱。
首先履植,創(chuàng)建一個(gè)腳本,繼承EditorWindow凿滤,也就是創(chuàng)建了一個(gè)編輯窗口了庶近,只不過沒有顯示罷了。
<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;
    
    //初始化投队,也就是一個(gè)MenuItem,當(dāng)點(diǎn)擊時(shí)調(diào)用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));   //獲取到窗口息楔,并且顯示
        //實(shí)例化并且設(shè)置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渲染圃泡,每幀調(diào)用
    void OnGUI()
    {
        //創(chuàng)建要顯示在編輯窗口的內(nèi)容
        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)   //點(diǎn)擊事件發(fā)生在當(dāng)前EditorWindow上
        {
            Vector2 mousePos = currentEvent.mousePosition;
            if (contextRect.Contains(mousePos)) //點(diǎn)在矩形范圍內(nèi)
            {
                menu.ShowAsContext();   //顯示menu
                currentEvent.Use();
            }
        }
    }

    //回調(diào)
    static void Callback(object obj)
    {
        Debug.Log("Selected: " + obj.ToString());
    }
}

這就是創(chuàng)建一個(gè)面板的代碼了颇蜡,可以直接復(fù)制到自己的工程中拯啦,創(chuàng)建如下窗口


MenuItem

窗口

對于里面的OnGUI代碼褒链,就是用到UnityEditor相關(guān)類中的一些類了,大家可以研究下甸鸟。
<strong>最后兵迅,文章就到這了,文筆有限刻恭,望大家見諒扯夭。
歡迎各路英雄互相討論學(xué)習(xí)。</strong>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市构拳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斗埂,老刑警劉巖凫海,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盐碱,死亡現(xiàn)場離奇詭異,居然都是意外死亡瓮顽,警方通過查閱死者的電腦和手機(jī)暖混,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晾咪,“玉大人贮配,你說我怎么就攤上這事≈缰” “怎么了圆存?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵沦辙,是天一觀的道長夫植。 經(jīng)常有香客問我,道長油讯,這世上最難降的妖魔是什么详民? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮撞羽,結(jié)果婚禮上阐斜,老公的妹妹穿的比我還像新娘。我一直安慰自己诀紊,他們只是感情好谒出,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著邻奠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碌宴。 梳的紋絲不亂的頭發(fā)上杀狡,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音贰镣,去河邊找鬼呜象。 笑死膳凝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恭陡。 我是一名探鬼主播蹬音,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼休玩!你這毒婦竟也來了著淆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拴疤,失蹤者是張志新(化名)和其女友劉穎永部,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呐矾,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苔埋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凫佛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讲坎。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愧薛,靈堂內(nèi)的尸體忽然破棺而出晨炕,到底是詐尸還是另有隱情,我是刑警寧澤毫炉,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布瓮栗,位于F島的核電站,受9級特大地震影響瞄勾,放射性物質(zhì)發(fā)生泄漏费奸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一进陡、第九天 我趴在偏房一處隱蔽的房頂上張望愿阐。 院中可真熱鬧,春花似錦趾疚、人聲如沸缨历。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辛孵。三九已至,卻和暖如春赡磅,著一層夾襖步出監(jiān)牢的瞬間魄缚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工焚廊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冶匹,地道東北人习劫。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像徙硅,于是被迫代替她去往敵國和親榜聂。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容