Unity編輯器擴展


一,菜單項相關操作

1.菜單項(MenuItem)

首先在Asset目錄下新建一個Editor文件夾,然后在該目錄下添加一個腳本MenuTest.cs
代碼內容:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MenuTest : MonoBehaviour {
/// <summary>
    /// _w 單一的快捷鍵 W
    /// #w shift + w
    /// %w ctrl + w
    /// &w alt + w
    /// </summary>
    [MenuItem("菜單/Test _w")]
    public static void Test1()
    {
        Debug.Log("Test1-----");
    }

    [MenuItem("菜單/Test# #w")]
    public static void Test2 ()
    {
        Debug.Log("Test2-----");
    }

    [MenuItem("菜單/Test% %w")]
    public static void Test3 ()
    {
        Debug.Log("Test3-----");
    }

    [MenuItem("菜單/Test& &w")]
    public static void Test4 ()
    {
        Debug.Log("Test4-----");
    }
}

2.組件菜單(AddComponentMenu)

代碼內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;
[AddComponentMenu("菜單組件/MenuTest")]
public class Test1 : MonoBehaviour {


}

 

3.上下文菜單(ContextMenu)

就是在一個物體的組件上添加上下文菜單,即點擊右鍵出現的菜單
就在上文的Test1中添加一個上下文菜單
代碼內容如下:

using UnityEngine;
using System.Collections;
using UnityEditor;
[AddComponentMenu("菜單組件/MenuTest")]
public class Test1 : MonoBehaviour {


    [ContextMenu("ContextMenu")]
    public void Test()
    {
        Debug.Log("上下文測試");
    }

}

 

4.必要組件菜單(RequireComponent)

必要組件是在添加改組件的同時添加其他的組件,而且是依賴於這個組件的,
同樣在上文的Test.cs中添加必要組件,
代碼內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;
[RequireComponent(typeof(Rigidbody))]
[AddComponentMenu("菜單組件/MenuTest")]
public class Test1 : MonoBehaviour {

    [ContextMenu("ContextMenu")]
    public void Test()
    {
        Debug.Log("上下文測試");
    }

}

 


二,自定義Inspector界面

1.屬性相關標識

1)隱藏屬性顯示 (HideInInspector)
2)不顯示的屬性(NonSerialized)
3)關鍵字序列化(Serializable)
4)序列化域(SerializeField)

 

首先新建腳本文件,InspectorTest.cs 和腳本Type1.cs
InspectorTest.cs:

using System;
using UnityEngine;
using System.Collections;

public class InspectorTest : MonoBehaviour
{

    public int number1 = 3;
    [HideInInspector]  //單純的隱藏屬性
    public int number2 = 3;
   [NonSerialized]   //不但隱藏,防止變量序列化
    public int number3 = 3;
    [SerializeField]    //將私有變量強制顯示出來
    private int number4 = 5;
    
    //[Serializable]可以讓自定義的類顯示在視圖面板
    public Type1 mytype;

}

Type1.cs腳本內容:(Type1類已經被序列化了)

using UnityEngine;
using System.Collections;
using System;

[Serializable]
public class Type1
{
    public int val1;

    public float val2;

    public Color color;

}

 

2.自定義界面屬性

這里會用到2個類 Editor 和CustomEditor
Editor是自定義面板的基類
CustomEditor是對應標識的組件腳本

案例1:自定義一個屬性面板
1)首先在Scripts文件夾下新建一個腳本文本OwnerUITest.cs
腳本內容為:

using System;
using UnityEngine;
using System.Collections;

public class OwerUITest : MonoBehaviour
{

    public int IntVal;

    public float FlatVal;

    public string StrVal;

    public Type3 mType = new Type3();


}

[Serializable]
public class Type3
{
    public int mInt;

    public int mInt2;
}

2)在Editor文件下新建腳本OwnerUIInspector.cs 這個類要繼承Editor類,而且要在類的前面聲明:[CustomEditor(typeof(OwerUITest))] 關聯剛才新建的腳本
腳本的內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(OwerUITest))]
public class OwnerUIInspector : Editor
{

    public SerializedObject mObj;

    public SerializedProperty mInt;

    public SerializedProperty mFloat;

    public SerializedProperty mStr;

    public SerializedProperty mtype;
    /// <summary>
    /// 選擇當前的游戲對象時執行
    /// </summary>
    public void OnEnable()
    {
        Debug.Log("OnEnable()------");
        this.mObj = new SerializedObject(target);
        this.mInt = this.mObj.FindProperty("IntVal");
        this.mFloat = this.mObj.FindProperty("FlatVal");
        this.mStr = this.mObj.FindProperty("StrVal");
        this.mtype = this.mObj.FindProperty("mType");
    }



    /// <summary>
    /// 繪制
    /// </summary>
    public override void OnInspectorGUI()
    {
        Debug.Log("OnInspectorGUI()------");
        this.mObj.Update();

        EditorGUILayout.PropertyField(this.mInt);
        EditorGUILayout.PropertyField(this.mFloat);
        EditorGUILayout.PropertyField(this.mStr);
        //true,表示顯示出類的子節點
        EditorGUILayout.PropertyField(this.mtype, true);

    }
}

 

1)首先在Scripts文件夾中新建一個腳本組件InspectorZiDingYi.cs,腳本代碼如下:

using UnityEngine;
using System.Collections;

public class InspectorZiDingYi : MonoBehaviour
{

    public MyEnum mEnum;

    public int mInt;

    public float FlatVal;

    public string StrVal;

    public Color mColor;
}


public enum MyEnum
{
    None,
    IntVal,
    FloatVal,
    StrVal,
    CocolVal
}

2)然后在Editor文件下新建一個類InspectorZiDingYIEditor 繼承Editor,然后與InspectorZiDingYi組件關聯,腳本代碼如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(InspectorZiDingYi))]
public class InspectorZiDingYIEditor : Editor
{

    public SerializedObject mObject;

    public SerializedProperty mEnum;

    public SerializedProperty mInt;

    public SerializedProperty mFloat;

    public SerializedProperty mStr;

    public SerializedProperty mColor;

    public void OnEnable()
    {
        this.mObject = new SerializedObject(target);
        this.mEnum = this.mObject.FindProperty("mEnum");
        this.mInt = this.mObject.FindProperty("mInt");
        this.mFloat = this.mObject.FindProperty("FlatVal");
        this.mStr = this.mObject.FindProperty("StrVal");
        this.mColor = this.mObject.FindProperty("mColor");
    }
    public override void OnInspectorGUI()
    {
        this.mObject.Update();

        EditorGUILayout.PropertyField(this.mEnum);

        switch (this.mEnum.enumValueIndex)
        {
            case 1:
                EditorGUILayout.PropertyField(this.mInt);
                break;
            case 2:
                EditorGUILayout.PropertyField(this.mFloat);
                break;
            case 3:
                EditorGUILayout.PropertyField(this.mStr);
                break;
            case 4:
                EditorGUILayout.PropertyField(this.mColor);
                break;
        }
        
        this.mObject.ApplyModifiedProperties();

    }
}

 

3.自定義窗口

-----------------------------界面的啟動和關閉--------------------------
創建自定義窗口需要繼承 基類:EditorWindow

案例1:點擊菜單項,彈出一個窗口
1)首先在Editor文件夾中創建一個腳本MyTestWindow.cs,腳本內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MyTestWindow : EditorWindow 
{
    [MenuItem("菜單/顯示窗口")]
    public static void showWindow()
    {
       MyTestWindow.CreateInstance<MyTestWindow>().Show();
    }
}

 

若修改顯示方式:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MyTestWindow : EditorWindow 
{
    [MenuItem("菜單/顯示窗口")]
    public static void showWindow()
    {
       MyTestWindow.CreateInstance<MyTestWindow>().ShowUtility();
    }
}

 

再換一種其他的顯示方式:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MyTestWindow : EditorWindow 
{
    [MenuItem("菜單/顯示窗口")]
    public static void showWindow()
    {
        MyTestWindow.CreateInstance<MyTestWindow>().ShowPopup();
    }
}

 

這樣顯示的面板是一個空的面板,無法關閉,我們再這個面板上增加一個關閉按鈕:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MyTestWindow : EditorWindow 
{
    [MenuItem("菜單/顯示窗口")]
    public static void showWindow()
    {
        MyTestWindow.CreateInstance<MyTestWindow>().ShowPopup();
    }
    public void OnGUI ()
    {
        if (GUILayout.Button("關閉"))
        {
            this.Close();
        }
    }
}

 

-----------------------------界面的相關事件機制------------------------

界面的相關事件機制總共有9個:
1.public void OnGUI() ->繪制窗口
2.public void Update() ->刷新方法,100次/3.public void OnInspectorUpdate() ->刷新方法,比Update()少
4.public void OnSelectionChange() ->選擇一個對象
5.public void OnDestroy ->銷毀窗口
6.public void OnFocus() ->獲得焦點
7.public void OnLostFocus() ->失去焦點
8.public void OnHierarchayChange() ->Hierarchay視圖窗口文件發生改變
9.public void OnProjectChange() ->Project視圖窗口文件發生改變

案例測試:
首先在Editor文件夾系新建腳本文件:MyWindow2,同樣首先繼承EditorWindow類,然后實現上述的9個事件機制函數,腳本內容如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class MyWindow2 : EditorWindow
{

    [MenuItem("菜單/窗口2")]
    public static void showWindwo()
    {
        //利用單例只可以打開一個窗口
        EditorWindow.GetWindow<MyWindow2>().Show();
    }

    /// <summary>
    /// 繪制操作面板
    /// </summary>
    public void OnGUI()
    {
        if(GUILayout.Button("關閉"))
        {
            this.Close();
        }
    }

    public int index_update = 0;

    public int index_OnInspectorUpdate = 0;

    /// <summary>
    /// 刷新,每秒100次
    /// </summary>
    public void Update()
    {
        index_update ++;
    }

    /// <summary>
    /// 刷新方法,比Update少
    /// </summary>
    public void OnInspectorUpdate()
    {
        index_OnInspectorUpdate ++;
    }
    /// <summary>
    /// 視圖被刪除
    /// </summary>
    public void OnDestroy()
    {
        Debug.Log("視圖被刪除");
    }

    /// <summary>
    /// 選擇對象發生改變
    /// </summary>
    public void OnSelectionChange()
    {

        //打印出場景里選擇的對象
        for (int i = 0; i < Selection.gameObjects.Length; i++)
        {
            Debug.Log("選擇一個場景內對象:" + Selection.gameObjects[i].name);
        }

        //打開所有選擇的對象
        for (int i = 0; i < Selection.objects.Length; i++)
        {
            Debug.Log("選擇一個對象:" + Selection.objects[i].name);
        }
    }

    public void OnFocus()
    {
        Debug.Log("OnFocus");
    }

    public void OnLostFocus()
    {
        Debug.Log("OnLostFocus");
    }

    /// <summary>
    /// HirearchyChange更改
    /// </summary>
    public void OnHierarchyChange()
    {
    
        Debug.Log("OnHierarchyChange");
       
    }

    /// <summary>
    /// Project 更改
    /// </summary>
    public void OnProjectChange()
    {
        Debug.Log("OnProjectChange");
    }

}

 

-----------------------------文本顏色字段------------------------
輸入框:

EditorGUILayout.TextField(string) 文本輸入框
EditorGUILayout.TextArea(string); 可換行的文本輸入框
EditorGUILayout.PasswordField(string); 文本輸入框
EditorGUILayout.ColorField(Color); 顏色輸入框

1)首先在Editor文件夾下新建腳本TextColorwindow.cs,文件內容如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class TextColorwindow : EditorWindow
{
    [MenuItem("菜單/文本顏色窗口")]
    public  static void showWindow()
    {
        EditorWindow.GetWindow<TextColorwindow>().Show();
    }
    public string mText = "please input a string";
    public Color mColor = Color.black;
    public void OnGUI()
    {
        this.mText = EditorGUILayout.TextField(this.mText);
        this.mText = EditorGUILayout.TextArea(this.mText);
        this.mText = EditorGUILayout.PasswordField(this.mText);
        this.mColor = EditorGUILayout.ColorField(this.mColor);
    }
}

 

-----------------------------標簽字段------------------------

標簽:
EditorGUILayout.LabelField(string) 文本標簽
EditorGUILayout.SelectableLabel(string); 選擇標簽
EditorGUILayout.Space(); 空一行

 

1)首先在Editor文件中新建腳本LabelWindow.cs 文件內容如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class LabelWindow : EditorWindow
{


    public string mText = "please input a string";

    public Color mColor = Color.black;

    [MenuItem("菜單/標簽窗口")]
    public static void showWindwo()
    {
        EditorWindow.GetWindow<LabelWindow>().Show();
    }


    public void OnGUI()
    {
        //文本標簽
        EditorGUILayout.LabelField("輸入文本");
        this.mText = EditorGUILayout.TextField(this.mText);
        //空一行
        EditorGUILayout.Space();
        EditorGUILayout.LabelField("輸入文本");
        this.mText = EditorGUILayout.TextArea(this.mText);
        //選擇標簽
        EditorGUILayout.SelectableLabel("輸入密碼");

        this.mText = EditorGUILayout.PasswordField(this.mText);
        EditorGUILayout.LabelField("選擇顏色");
        this.mColor = EditorGUILayout.ColorField(this.mColor);
    }
}

 

-----------------------------數字輸入框------------------------

數字輸入
EditorGUILayout.IntField(this.mIntVal); 整數輸入
EditorGUILayout.FloatField(this.mFloatVal); 浮點數輸入

 

1)首先在Editor文件夾中加入腳本Numberwindow.cs,文件內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class Numberwindow : EditorWindow 
{

    [MenuItem("菜單/數字輸入窗口")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<Numberwindow>().Show();
    }

    public int mIntVal;

    public float mFloatVal;


    public void OnGUI()
    {
        EditorGUILayout.LabelField("輸入整數");
        this.mIntVal = EditorGUILayout.IntField(this.mIntVal);

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("輸入浮點數");
        this.mFloatVal = EditorGUILayout.FloatField(this.mFloatVal);
    }
}

 

-----------------------------滾動條------------------------

EditorGUILayout.Slider(...) 浮點數滾動條
EditorGUILayout.IntSlider(...)整數滾動條
EditorGUILayout.MinMaxSlider(...)

 

1)首先在Editor文件夾下新建一個腳本ScrollWindow.cs,腳本內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class ScrollWindow : EditorWindow
{

    [MenuItem("菜單/滾動條窗口")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<ScrollWindow>().Show();
    }

    public float mFloat;

    public int mIntVal;

    public float mMinVal;
    public float mMaxVal;
    

    public void OnGUI()
    {

        this.mFloat = EditorGUILayout.Slider(this.mFloat, 0, 100);

        this.mIntVal = EditorGUILayout.IntSlider(this.mIntVal, 0, 100);

        EditorGUILayout.Space();


        this.mMinVal = EditorGUILayout.Slider(this.mMinVal, 0, 100);

        this.mMaxVal = EditorGUILayout.Slider(this.mMaxVal, 0, 100);

        EditorGUILayout.MinMaxSlider(ref this.mMinVal, ref this.mMaxVal, 0 , 100);
    }

-----------------------------位置大小輸入字段------------------------

位置字段:
EditorGUILayout.Vector2Field(string, Vector2) 二維坐標
EditorGUILayout.Vector3Field(string,Vector3); 三維坐標
EditorGuILayout.Vector4Field(string,Vector4);四維坐標
EditorGUILayout.RectFiled(Rect); 矩陣
EditorGUILayout.BoundsFiled();距離

 

1)首先在Editor文件夾下新建腳本PositionWindow.cs ,腳本內容如下:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class PositionWindow : EditorWindow
{

    public Vector2 mPos2;

    public Vector3 mPos3;

    public Vector4 mPos4;

    public Rect mRect;

    public Bounds mBounds;


    [MenuItem("菜單/位置輸入窗口")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<PositionWindow>().Show();
    }

    public void OnGUI()
    {

        this.mPos2 = EditorGUILayout.Vector2Field("二維坐標",this.mPos2);

        this.mPos3 = EditorGUILayout.Vector3Field("三維坐標", this.mPos3);

        this.mPos4 = EditorGUILayout.Vector4Field("四維坐標", this.mPos4);

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("矩陣");
        this.mRect = EditorGUILayout.RectField(this.mRect);
        
        EditorGUILayout.Space();

        EditorGUILayout.LabelField("距離");
        this.mBounds = EditorGUILayout.BoundsField(this.mBounds);
    }
}

 

-----------------------------選擇字段------------------------

選擇字段:
EditorGUILayout.Popup(int, string[]); 字符串選擇,返回字符串數組下標
EditorGUILayout.IntPopup(int,int[],string[]) 字符串選擇,返回字符串對應下標的整形數組值
EditorGUILayout.EnumPopup(Enum) 枚舉選擇,返回枚舉

1)首先在Editor文件夾下新建文件SelectWindow.cs ,腳本內容為:

 

using UnityEngine;
using System.Collections;
using UnityEditor;

public class SelectWindow : EditorWindow 
{

    public  int index;
    public EnumTest mEnum;

    [MenuItem("菜單/選擇字段測試窗口")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<SelectWindow>().Show();
    }
    public void OnGUI()
    {
        string[] strs = new[]
        {
            "數組下標0",
            "數組下標1",
            "數組下標2",
        };

        int[] intArr = new[]
        {
            1,
            2,
            3,
        };
        //字符選擇,返回選擇的字符數組下標
        this.index = EditorGUILayout.Popup(this.index, strs);
        //字符選擇,返回對應的整數數組的整數值
        this.index = EditorGUILayout.IntPopup(this.index, strs,intArr);
        Debug.Log("index:" + index);
        //枚舉選擇
        this.mEnum = (EnumTest)EditorGUILayout.EnumPopup(this.mEnum);
    }
}
public enum EnumTest
{
    Int1,
    Str2,
    Float3,
    Color4
}

 

-----------------------------標簽、層、對象選擇字段------------------------

1)首先在Editor文件夾下新建一個腳本TagLayer.cs,腳本的內容為:

using System;
using UnityEngine;
using System.Collections;
using UnityEditor;

public class TagLayer : EditorWindow 
{

    [MenuItem("菜單/標簽、層、對象選擇")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<TagLayer>().Show();
    }

    public String mTag;

    public int mLayer;

    public UnityEngine.Object mObject;

    public void OnGUI()
    {
        mTag = EditorGUILayout.TagField(this.mTag);

        mLayer = EditorGUILayout.LayerField(this.mLayer);

        mObject = EditorGUILayout.ObjectField(this.mObject, typeof(Camera));
    }
}

 

-----------------------------單選選擇字段-----------------
1)首先在Editor文件夾下新建ToggleWindow.cs腳本文件,腳本內容:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class ToggleWindow : EditorWindow 
{

    [MenuItem("菜單/單選字段選擇")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<ToggleWindow>().Show();
    }

    public bool mIsSelect;
    public void OnGUI()
    {

        this.mIsSelect = EditorGUILayout.Toggle("選擇", this.mIsSelect);
        this.mIsSelect = EditorGUILayout.Foldout(this.mIsSelect, "折疊");
        if(this.mIsSelect)
        {
            EditorGUILayout.LabelField("you and me");
            EditorGUILayout.LabelField("you and me");
            EditorGUILayout.LabelField("you and me");
            EditorGUILayout.LabelField("you and me");
            EditorGUILayout.LabelField("you and me");
        }
    }
}

 

-----------------------------字段分組-----------------

1)首先在Editor文件夾下新建腳本文件GroupWindow,腳本內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class GroupWindow : EditorWindow
{

    [MenuItem("菜單/字段分組")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<GroupWindow>().Show();

    }


    public bool mSelect;

    public Vector2 mPos;


    public void OnGUI()
    {
        //滾動分組----Begin
        this.mPos = EditorGUILayout.BeginScrollView(this.mPos);
        Debug.Log("滾動分組測試位置:" + this.mPos);

        //Toggle分組----Begin
        this.mSelect = EditorGUILayout.BeginToggleGroup("選擇分組",this.mSelect);

        EditorGUILayout.LabelField("1");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("2");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("3");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("4");
        EditorGUILayout.TextField("sdk");

        EditorGUILayout.EndToggleGroup();
        //Toggle分組-----End

        EditorGUILayout.Space();

        //水平分組----Begin
        Rect rect1 = EditorGUILayout.BeginHorizontal();

        EditorGUILayout.LabelField("5");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("6");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("7");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("8");
        EditorGUILayout.TextField("sdk");
        Debug.Log( "水平分組測試數據:" + rect1);

        EditorGUILayout.EndHorizontal();
        //水平分組----End


        //垂直分組----Bengin
        Rect rect2 = EditorGUILayout.BeginVertical();

        EditorGUILayout.LabelField("5");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("6");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("7");
        EditorGUILayout.TextField("sdk");
        EditorGUILayout.LabelField("8");
        EditorGUILayout.TextField("sdk");

        EditorGUILayout.EndVertical();
        //垂直分組----End


        //滾動分組-----End
        EditorGUILayout.EndScrollView();

    }
}

 

-----------------------------其他字段-----------------
1)首先在Editor文件夾下新建OtherWindow.cs腳本文件,腳本內容為:

using UnityEngine;
using System.Collections;
using UnityEditor;

public class OtherFiledWindow : EditorWindow 
{
    [MenuItem("菜單/其他字段")]
    public static void showWindow()
    {
        EditorWindow.GetWindow<OtherFiledWindow>().Show();
    }

    public AnimationCurve mAC = new AnimationCurve();


    public bool mSelect;

    public Object mObj;

    public void OnGUI()
    {
        //動畫字段
        this.mAC = EditorGUILayout.CurveField("動畫片段",this.mAC);

        //獲得選擇的物體
        this.mObj = EditorGUILayout.ObjectField(this.mObj, typeof (Transform));

        //將選擇的物體放在面板上
        this.mSelect = EditorGUILayout.InspectorTitlebar(this.mSelect,this.mObj);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM