Unity 編輯器擴(kuò)展一 常用屬性

參考
Unity 編輯器擴(kuò)展總結(jié) 一:編輯器開發(fā)入門
Unity 編輯器擴(kuò)展總結(jié) 二:編輯器的相關(guān)特性
Unity Editor 基礎(chǔ)篇(一):Build-In Attribute
Unity拓展編輯器入門指南

一、簡單示例(編輯器擴(kuò)展是做什么的)

使用Visual studio在Assets/Editor下新建項(xiàng)


visual studio新建項(xiàng)

選Editor Script

腳本名就用默認(rèn)的,visual studio會自動生成一個模板代碼

using UnityEditor;
using UnityEngine;

namespace Assets.Editor
{
    public class NewEditorScript1 : ScriptableObject
    {
        [MenuItem("Tools/MyTool/Do It in C#")]
        static void DoIt()
        {
            EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");
        }
    }
}

菜單上會多出一個選項(xiàng)

這里把: ScriptableObject去掉也沒關(guān)系,關(guān)于ScriptableObject以后再做了解。

在上面的示例中,通過指定MenuItem第二個參數(shù)為true,表示DeleteValidate為此菜單的有效函數(shù)。Selection.objects.Length == 0,此菜單才生效。

using UnityEditor;
using UnityEngine;

namespace Assets.Editor
{
    public class NewEditorScript1 : ScriptableObject
    {
        [MenuItem("Tools/MyTool/Do It in C#", true)]
        private static bool DeleteValidate()
        {
            if (Selection.objects.Length == 0)
                return true;
            else
                return false;
        }

        [MenuItem("Tools/MyTool/Do It in C#")]
        static void DoIt()
        {
            EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");
        }
    }
}

選項(xiàng)變灰了

unity編輯器擴(kuò)展#2 GUILayout、EditorGUILayout 控件整理
unity編輯器擴(kuò)展#3 《Extending Unity with Editor Scripting 》筆記

一、常用屬性
[MenuItem(“MyTools/test1”,false,priority)]

前兩個參數(shù)上面已經(jīng)解釋用處,第三個參數(shù)priority是優(yōu)先級,用來表示菜單按鈕的先后順序,默認(rèn)值為1000。一般菜單中的分欄,數(shù)值相差大于10。

1.實(shí)現(xiàn)點(diǎn)擊菜單按鈕,刪除場景或者Project中選中的多個對象
[MenuItem("MyTool/DeleteAllObj", true)]
private static bool DeleteValidate()   
{
    if (Selection.objects.Length > 0)
        return true;
    else
        return false;
}

[MenuItem("MyTool/DeleteAllObj",false)]
private static void MyToolDelete()
{
    //Selection.objects 返回場景或者Project中選擇的多個對象
    foreach (Object item in Selection.objects)
    {
        //記錄刪除操作,允許撤銷
        Undo.DestroyObjectImmediate(item);
    }
} 
2.Selection 用于獲取選擇的游戲物體
  • Selection.activeGameObject 返回第一個選擇的場景中的對象
  • Selection.gameObjects 返回場景中選擇的多個對象,包含預(yù)制體等
  • Selection.objects 返回選擇的多個對象
//遍歷選擇的對象,并立刻銷毀
foreach(object obj in Selection.objects)
{
    DestroyImmediate(obj);
}

P.S. Destroy方法會將刪除的對象放在緩存中,緩存滿了,才完全刪除,而在編輯器未運(yùn)行的時候,是沒有這片緩存的,所以需要用DestroyImmediate(),立刻銷毀。當(dāng)然,可以直接使用Undo.DestroyObjectImmediate()來銷毀對象并記錄銷毀操作。

3.添加快捷鍵
  • % Ctr/Command
  • # Shift
  • & Alt
  • LEFT/Right/UP/DOWN 方向鍵
  • F1-F2 F功能鍵
  • _g 字母g

例如:[MenuItem(“MyTools/test1 %_q”)] 快捷鍵 Ctrl+Q

4.CONTEXT給某組件添加右鍵菜單選項(xiàng)

[MenuItem(“CONTEXT/組件名/按鈕名”)]
注意CONTEXT大寫

[MenuItem("CONTEXT/Rigidbody/Init")]
private static void RigidbodyInit() 
{
    //TODO
}

5.MenuCommand用于獲取當(dāng)前操作的組件

如下,給自定義的組件PlayerHealth添加右鍵Init按鈕

[MenuItem("CONTEXT/PlayerHealth/Init")]
static void Init(MenuCommand cmd)
{
    PlayerHealth health = cmd.contex as PlayerHealth;
}
6.ContextMenu、ContextMenuItem

給某組件添加右邊小齒輪菜單選項(xiàng)

[ContextMenu("FunctionName")]
public void FunctionName()
{
    //ToDo
}

給某屬性添加右鍵菜單選項(xiàng)

[ContextMenuItem("Handle", "HandleHealth")]
public float health;

private void HandleHealth()
{
    //ToDo
}

P.S. 這兩個特性是在UnityEngine命名空間下的,而不像其他[MenuItem]、Selection是在UnityEditor下的。

7.常用的屬性特性
  • [Range(0,100)] //限制數(shù)值范圍
  • [Multiline(3)] //字符串多行顯示
  • [TextArea(2,4)] //文本輸入框
  • [SerializeField] //序列化字段,主要用于序列化私有字段
  • [NonSerialized] //反序列化一個變量,并且在Inspector上隱藏
  • [HideInInspector] //public變量在Inspector面板隱藏
  • [FormerlySerializedAs(“Value1”)] //當(dāng)變量名發(fā)生改變時,可以保存原來Value1的值
  • [ContextMenu(“TestBtn”)] //組件右鍵菜單按鈕
  • [ContextMenuItem(“Reset Value”,“Reset”)] //定義屬性的右鍵菜單
  • [Header(“Header Name”)] //加粗效果的標(biāo)題
  • [Space(10)] //表示間隔空間,數(shù)字越大,間隔越大
  • [Tooltip(“Tips”)] //顯示字段的提示信息
  • [ColorUsage(true)] //顯示顏色面板
image.png
通過Space進(jìn)行布局分割
8.常用的方法特性
  • [DrawGizmo] //用于Gizmos渲染,將邏輯與調(diào)試代碼分離
  • [MenuItem] //添加菜單項(xiàng)
9.常用的類的特性
  • [Serializable] //序列化一個類,作為一個子屬性顯示在監(jiān)視面板
  • [RequireComponent(typeof(Animator))] //掛載該類的對象,必須要有Animator組件
  • [DisallowMultipleComponent] //不允許掛載多個該類或其子類
  • [ExecuteInEditMode] //允許腳本在編輯器未運(yùn)行的情況下運(yùn)行
  • [CanEditMultipleObjects] //允許當(dāng)選擇多個掛有該腳本的對象時,統(tǒng)一修改值
  • [AddComponentMenu] //可以在菜單欄Component內(nèi)添加組件按鈕
  • [CustomEditor] //要自定義編輯器就要加這個特性
  • [CustomPropertyDrawer] //用于繪制自定義PropertyDrawer的特性
  • [SelectionBase] //選擇在場景視圖中使用此屬性的組件對象,即不會誤選中子物體

P.S. 多個特性可以用逗號隔開,例如:[SerializeField, Range(0,5)]

我們既想保證類的某個字段不被其他的類訪問修改,又想在Inspector視窗中修改這個字段的值的話,就可以采用private +[SerializeField]屬性的方案。

[SerializeField]
private int privateInt;
image.png
10.AddComponentMenu

AddComponentMenu 屬性允許將一個腳本添加到 Component 菜單中,然后你便可以通過 Component ->(你設(shè)置的名字)為一個選中的游戲?qū)ο髣?chuàng)建該腳本

[AddComponentMenu("Learn/Test")]
public class Test1 : MonoBehaviour
image.png
11.[RequireComponent(typeof(Animator))]

RequireComponent()屬性會自動幫你添加你需要的組件,如果已經(jīng)存在則不再重復(fù)添加,且不能移除

[AddComponentMenu("Learn/Test")]
[RequireComponent(typeof(Rigidbody))]
public class Test1 : MonoBehaviour
{
嘗試移除失敗

提示:經(jīng)過測試,我發(fā)現(xiàn)一個問題,如果腳本已經(jīng)掛在物體身上,然后再修改腳本,添加 RequireComponent 屬性的話,完全不起作用,因此建議大家在用此屬性的時候要注意。

12.ContextMenu

ContextMenu()屬性允許添加一個命令到該組件上,你可以通過右鍵或者點(diǎn)擊設(shè)置圖標(biāo)來調(diào)用到它(一般用于函數(shù)),且是在非運(yùn)行狀態(tài)下執(zhí)行該函數(shù),如下所示:

[AddComponentMenu("Learn/Test")]
[RequireComponent(typeof(Rigidbody))]
public class Test1 : MonoBehaviour
{
    public Text Text1;
    public bool myBool;
    public string myString;

    [ContextMenu("OutputInfo")]
    void OutputInfo()
    {
        Debug.Log("outputinfo");
    }
}
image.png
13.HelpURL

HelpURL()提供一個自定義的文檔鏈接,點(diǎn)擊組件上的文檔圖標(biāo)既能打開到你指定的鏈接,如下所示:

[HelpURL("http://www.baidu.com")]
[AddComponentMenu("Learn/Test")]
[RequireComponent(typeof(Rigidbody))]
public class Test1 : MonoBehaviour
image.png
14.Range、Multiline、header

Range()屬性用于將一個值指定在一定的范圍內(nèi),并在Inspector面板中為其添加滑塊;Multiline()屬性用于給 string 類型添加多行輸入;header()屬性用于添加屬性的標(biāo)題,具體操作如下所示:

public class Test1 : MonoBehaviour
{
    public Text Text1;
    public bool myBool;

    [Header("BaseInfo")]
    [Multiline(5)]
    public string myString;

    [Range(-2, 2)]
    public int age;
image.png
15.Tooltip、Space

Tooptip()屬性用于在 Inspector 面板中,當(dāng)鼠標(biāo)停留在設(shè)置了Tooptip()的屬性添加指定的提示;Space()用于為在 Inspector 面板兩屬性之間添加指定的距離,如下所示:

    [Range(-2, 2)]
    public int age;

    [Space(100)]
    [Tooltip("用于設(shè)置性別")]
    public string sex;
image.png
二、編輯器相關(guān)文件夾介紹
1.Editor
  • 該文件夾可以放在項(xiàng)目的任何文件夾下,可以有多個"Editor"文件夾。
  • 編輯器擴(kuò)展相關(guān)的腳本都要放在該文件夾內(nèi),該文件夾中的腳本只會對Unity編輯器起作用。
  • 項(xiàng)目打包的時候,不會被打包到項(xiàng)目中。如果編輯器相關(guān)腳本不放在該文件夾中,打包項(xiàng)目可能會出錯。
  • 如果非要有些編輯器相關(guān)腳本不放在該文件夾中,需要在該類的前后加上UNITY_EDITOR的宏定義
2.Editor Default Resources
  • 該文件夾需要放在Assets根目錄下,用來存儲編輯器所需要的圖片等資源,書寫的時候需要注意中間有空格隔開。此文件夾也不會被打包,訪問方法為:EditorGUIUtility.Load()
  • 當(dāng)然,也可以在Editor文件夾內(nèi)創(chuàng)建一個Resources文件夾,將相關(guān)資源放在該文件夾內(nèi),通過Resources.Load()獲取資源,也是可以的
3.Gizmos
  • 該文件夾也需要放在Assets根目錄下,可以用來存放Gizmos.DrawIcon()的圖片資源
4.一般繼承MonoBehaviour的腳本都放在Assets/Scripts文件夾里,而使用using UnityEditor;這個命名空間的腳本都放在Assets/Editor文件夾里。本系列文章后續(xù)例子中的代碼,不再重復(fù)說明此點(diǎn)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容