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
第一個類用於在組件的右鍵中添加擴展。
在別的腳本中寫其他腳本的擴展需要使用靜態方法。
在本腳本中添加擴展,不需要使用靜態方法。
- 對系統組件添加擴展
[MenuItem("CONTEXT/Rigidbody/Clear")]
//CONTEXT(默認寫法) , 組件名 , 擴展名
static void ClearMassGravity(MenuCommand cmd)
//MenuCommand是當前正在操作的組件對象。只要定義就行,系統會自動賦值
{
Rigidbody rgd = cmd.context as Rigidbody;
//MenuCommand.context為正在操作的組件對象
rgd.mass = 0;
}
- 對自定義腳本添加擴展
//自定義腳本的話可以在別的腳本里面寫,也可以在本腳本寫。
//一般都在本腳本寫,因為可以更方便的訪問腳本中已經存在的游戲物體
[ContextMenu("SetColor")]
void SetColor()
{
flashColour = Color.green;
}
- 對腳本的屬性添加擴展
//屬於MonoBehaviour,不需要引用Editor。
//第一個參數為擴展名,第二個為方法名
[ContextMenuItem("Add", "AddHp")]
public int startingHealth = 100;
void AddHp()
{
startingHealth += 20;
}
2.7、ScriptableWizard---對話框
當參與的項目非常大時,假如LOL。如果想把所有英雄的HP都一起修改時,使用之前的方法就要一個一個的修改,工作量巨大。
那么有沒有更加簡單的方法呢?
-
靜態方法---對話框的創建
DisplayWizard<類名>(對話框名,Create按鈕名,OtherButton按鈕名); -
事件---對話框按鈕事件
OnWizardCreate:Create按鈕事件名
OnWizardOtherButton:OtherButton按鈕事件名
OnWizardUpdate:打開對話框或改變對話框內容時調用此方法 -
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();
}
}
