Unity---編輯器擴展




1、Unity編輯器擴展介紹

Unity為開發者們提供了很方便的擴展功能,編輯器擴展主要可以用於在Unity界面中添加屬於自己的菜單、插件。有時可以大大的提高開發效率。
用於編輯器擴展的腳本都放在Editor文件夾中,此文件夾中的資源不會在項目發布時候打包。

2、具體功能

在使用擴展功能時,需要引用UnityEditor命名空間

2.1、在菜單欄中添加擴展

在菜單欄中的擴展可以自己新創,也可以加在已有的菜單里面。

using UnityEditor;                 
public class Tools 
{    
	[MenuItem("MyTools/Test1")]    //讓其顯示在菜單欄MyTools-Test1下,MyTest1方法表示要做的工作
	//放在其下面的方法代表調用這個。上面寫的是路徑名字
	private static void MyTest1()          //只有靜態方法可以使用MenuItem屬性
	{         
		Debug.Log("擴展1");
	}
}

[MenuItem("MyTools/Test1",false,1)]
第一個參數:顯示在菜單欄的位置
第二個參數:是否為驗證函數,默認為false
第三個參數:優先級,默認為1000。優先級越大越靠下面,優先級相差>10時,會出現分隔符

2.2、為擴展事件添加快捷鍵

[MenuItem("MyTools/Test1 %t",false,11)]
在第一個參數后面加空格然后寫要加的快捷鍵。
此例就代表快捷鍵為 Ctrl+t

% == Ctrl
# == Shift
& == alt

2.3、在Hierarchy,Project視圖中右鍵添加擴展

Hierarchy視圖右鍵下的基本都是GameObject菜單第一層分割線之上的擴展。
那么只要把擴展放在第一層的分割線之上不就行了。
而優先級為11則剛好在第一層分割線的最后一個。
[MenuItem("GameObject/Test1",false,11)]

Project右鍵下的選項基本都在Assets目錄下,添加方法同上。

2.4、使用Selection類選擇游戲物體

Selection屬於UnityEditor命名空間。

//返回選擇場景中的一個游戲物體或者預制體。未選擇會報錯返回none,選擇多個會返回第一個。
GameObject go1 = Selection.activeGameObject;

//返回選擇場景中的一個游戲物體或預制體、腳本等任意物體。未選擇會報錯返回none,選擇多個會返回第一個。
Object object1 = Selection.activeObject;

//返回選擇場景中的一個游戲物體。未選擇會報錯返回none,選擇多個會返回第一個。
Transform transform = Selection.activeTransform;


//返回GameObject類型數組,為選擇場景中的多個游戲物體或者預制體。只會選擇符合條件的,未選擇則數組長度為0。
GameObject[] gameObjects = Selection.gameObjects;

//返回Object類型數組,為選擇場景中的多個游戲物體或者任意資源。只會選擇符合條件的,未選擇則數組長度為0。
Object[] objects = Selection.objects;

//返回transform類型數組,為選擇場景中的多個游戲物體。只會選擇符合條件的,未選擇則數組長度為0。
Transform[] transforms = Selection.transforms;

2.5、Menuitem第二個參數

使用第二個參數時一般配合兩個方法來使用。

    [MenuItem("SelectionTest/Test1 _t", true, 1)]
    static bool Test()
    {
        if (Selection.activeTransform == null)
            return false;
        return true;
    }

    [MenuItem("SelectionTest/Test1 _t",false,1)]
    static void Test1()
    {
        Debug.Log(Selection.activeTransform.name);
    }

第二個方法在未選擇物體時,本來會報錯none。
當使用第二個參數設為true時,只有當此函數返回為true,才會繼續執行下面的函數。
那么當未選擇物體時,第一個函數返回false,就不會再進行第二個函數。就避免了報錯的情況。

注意:MenuItem里的游戲路徑和名稱必須都相同。

2.6、ContextMenu和ContextMenuItem

第一個類用於在組件的右鍵中添加擴展。
別的腳本中寫其他腳本的擴展需要使用靜態方法
本腳本中添加擴展,不需要使用靜態方法

  1. 對系統組件添加擴展
	[MenuItem("CONTEXT/Rigidbody/Clear")]
		//CONTEXT(默認寫法) , 組件名 , 擴展名
	static void ClearMassGravity(MenuCommand cmd)
		//MenuCommand是當前正在操作的組件對象。只要定義就行,系統會自動賦值
	{
	    Rigidbody rgd = cmd.context as Rigidbody;
		//MenuCommand.context為正在操作的組件對象
	    rgd.mass = 0;
	}
  1. 對自定義腳本添加擴展
	//自定義腳本的話可以在別的腳本里面寫,也可以在本腳本寫。
	//一般都在本腳本寫,因為可以更方便的訪問腳本中已經存在的游戲物體
	[ContextMenu("SetColor")]
    void SetColor()
    {
        flashColour = Color.green;
    }
  1. 對腳本的屬性添加擴展
	//屬於MonoBehaviour,不需要引用Editor。
	//第一個參數為擴展名,第二個為方法名
    [ContextMenuItem("Add", "AddHp")]
    public int startingHealth = 100;   
	void AddHp()
    {
        startingHealth += 20;
    }  

2.7、ScriptableWizard---對話框

當參與的項目非常大時,假如LOL。如果想把所有英雄的HP都一起修改時,使用之前的方法就要一個一個的修改,工作量巨大。
那么有沒有更加簡單的方法呢?

  1. 靜態方法---對話框的創建
    DisplayWizard<類名>(對話框名,Create按鈕名,OtherButton按鈕名);

  2. 事件---對話框按鈕事件
    OnWizardCreate:Create按鈕事件名
    OnWizardOtherButton:OtherButton按鈕事件名
    OnWizardUpdate:打開對話框或改變對話框內容時調用此方法

  3. OnEnable:當對話框被創建時調用一次

using UnityEngine;
using UnityEditor;

public class EnemyChange : ScriptableWizard {

    public int changeStartHpValue = 150;
    public int ChangeSinkSpeed = 11;
    public const string changeStartHpValueKey = "changeStartHpValue";
    public const string ChangeSinkSpeedKey = "ChangeSinkSpeed";

    //創建對話框擴展
    [MenuItem("Tools/CreateWizard")]
    static void CreateWizard()
    {
        DisplayWizard<EnemyChange>("統一修改敵人","Change And Close","Change");
        //EnemyChange為類名,對話框名字,Create按鈕的名字,OtherButton按鈕名字
        //第2、3參數都可以省略
        //Create點擊后會關閉對話框,OtherButton按鈕點擊后不會關閉對話框
    }

    //檢測Create按鈕點擊的自帶方法
    private void OnWizardCreate()
    {
        GameObject[] enemyPrefabs =  Selection.gameObjects;

        int count = 0;
        EditorUtility.DisplayProgressBar("進度", count + "/" + enemyPrefabs.Length, 0);

        foreach (GameObject go in enemyPrefabs)
        {
            //獲取物體的EnemyHealth腳本
            CompleteProject.EnemyHealth hp = go.GetComponent<CompleteProject.EnemyHealth>();
            Undo.RecordObject(hp, "Change Health And Speed");   //開始記錄對hp的更改,之后對其的更改都可以撤銷

            //改變物體的屬性
            hp.startingHealth = changeStartHpValue;
            hp.sinkSpeed = ChangeSinkSpeed;

            count++;
            EditorUtility.DisplayProgressBar("進度", count + "/" + enemyPrefabs.Length, (float)count/enemyPrefabs.Length);
        }
        EditorUtility.ClearProgressBar();
    }

    //檢測Other Button按鈕方法
    private void OnWizardOtherButton()
    {
        OnWizardCreate();
        ShowNotification(new GUIContent(Selection.gameObjects.Length + "值被修改了"));
    }

	//打開對話框或改變對話框內容時調用此方法
    private void OnWizardUpdate()
    {
        helpString = "";
        errorString = "";
        if(Selection.gameObjects.Length > 0)
        {
            helpString = "您當前選擇了" + Selection.gameObjects.Length + "個敵人";
        }
        else
        {
            errorString = "請選擇至少一個敵人";
        }
        EditorPrefs.SetInt("changeStartHpValue", changeStartHpValue);
        EditorPrefs.SetInt("ChangeSinkSpeed", ChangeSinkSpeed);
    }

	//當窗口被創建時調用
    private void OnEnable()
    {
        changeStartHpValue = EditorPrefs.GetInt(changeStartHpValueKey, changeStartHpValue);
        ChangeSinkSpeed = EditorPrefs.GetInt(ChangeSinkSpeedKey, ChangeSinkSpeed);
        
    }

    //打開修改選中的物體時調用此方法
    private void OnSelectionChange()
    {
        OnWizardUpdate();
    }
}


免責聲明!

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



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