目錄
擴展布局 (Project 視圖腳本 代碼的右側擴展自定義按鈕)
擴展布局(點擊Hierarch中的遊戲對象在右側擴展出一組按鈕 )
擴展Project視圖中的右鍵視圖菜單
● 編譯器使用的代碼應該僅限於編輯模式下, 也就是說正式的遊戲包不應該包含這些代碼。
● Unity的C#腳本分爲兩種,一種是給遊戲本身運行的,一種是個編輯器運行的;其中給編輯器運行的腳本必須在Editor文件夾下,如果屬於運行時執行的代碼,放在任意非 Editor 文件夾下即可。
● 可以把腳本資源放在一個命名爲scripts的文件夾下。
● 如何創建My Tools 菜單集合:
首先先跟上述那樣操作,創建一個Scripts文件夾,然後子文件夾Editor,然後鼠標右鍵Editor 文件夾點擊: Create-------->C# scripts. 這樣。
然後把下列代碼打進去:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class Script_03_01
{
[MenuItem("Assets/My Tools/Tools 1", false, 2)]
static void MyTools1()
{
Debug.Log(Selection.activeObject.name);
}
[MenuItem("Assets/My Tools/Tools 2", false, 1)]
static void MyTools2()
{
Debug.Log(Selection.activeObject.name);
}
}
然後切換到Unity3D,後發現右下角,有一個在轉圈的東西,這是Unity再編譯你剛剛改的代碼;帶起轉圈完畢後,就說明編譯好了。
然後在project視圖中的腳本代碼上鼠標右鍵 或者 主菜單欄上的Assets裏就能看見我們在Unity 中擴展的功能。
我們點擊其中一個 Tools, 就會在 Console 中
輸出相應的日誌了、
● 說明: 自定義菜單的參數需要在MenuItem 方法中寫入顯示的菜單路徑。 如果菜單條比較多,可以在第三個參數處輸入表示排序的整數,數值越小,它的排序就越靠越靠前。 最後使用 Debug.Log 打印選擇的遊戲對象 Selection.activeObject.name 即可。
在project視圖中的Create按鈕中擴展資源創建菜單
● 跟上面方法一樣,貼代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_02
{
[MenuItem("Assets/Create/My Create/Cube", false, 2)]
static void CreateCube()
{
GameObject.CreatePrimitive(PrimitiveType.Cube); //創建立方體
}
[MenuItem("Assets/Create/My Create/Sphere", false, 1)]
static void CreateSphere()
{
GameObject.CreatePrimitive(PrimitiveType.Sphere);//創建球體
}
}
● 擴展菜單的關鍵就是找到正確的菜單路徑,通過 “/ ” 符號將它們拼合而成,
● GameObject.CreatePrimitive (PrimitiveType. Type) 方法用於創建 Unity 基礎原始遊戲對象;
參數Type表示要創建的原始對象的類型。
最後成功擴展了 My Create 菜單:
using UnityEngine;
public class Example : MonoBehaviour
{
//在場景中創建一個平面,球體,立方體,膠囊,圓柱體
void Start()
{
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = new Vector3(0, 0.5f, 0);
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = new Vector3(0, 1.5f, 0);
GameObject capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);
capsule.transform.position = new Vector3(2, 1, 0);
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
cylinder.transform.position = new Vector3(-2, 1, 0);
}
}
擴展布局 (Project 視圖腳本 代碼的右側擴展自定義按鈕)
● 跟上面描述的方法一樣, 先寫 C# Script, 代碼:
using UnityEngine;
using UnityEditor;
public class Script_03_03
{
[InitializeOnLoadMethod]
static void InitializeOnLoadMethod()
{
EditorApplication.projectWindowItemOnGUI = delegate (string guid, Rect selectionRect)
{
//在Project視圖中選擇一個資源
if (Selection.activeObject &&
guid == AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject)))
{
//設置拓展按鈕區域
float width = 50f;
selectionRect.x += (selectionRect.width - width);
selectionRect.y += 2f;
selectionRect.width = width;
GUI.color = Color.red;
//點擊事件
if (GUI.Button(selectionRect, "click"))
{
Debug.LogFormat("click : {0}", Selection.activeObject.name);//使用 Debug.Log 打印選擇的遊戲對象 Selection.activeObject.name 即可。
}
GUI.color = Color.white;
}
}; //這裏要添加分號
}
}
● 這樣就可以在Project 視圖 代碼的右側擴展自定義按鈕, 在代碼中既可以設置按鈕的區域,也可以監聽按鈕的事件。
可以看到圖中的一個資源的上面有一個擴展後的按鈕, 點擊這個按鈕, 程序會自動在 Console 窗口中打印選中的資源名。看下圖,點擊後,Console 打印的信息:
● EditorApplication.projectWindowItemOnGUI :爲ProjectWindow中的每個可見列表項委託GUI事件
● Delegate至少0個參數,至多32個參數,可以無返回值,也可以指定返回值類型。
● AssetDatabase.AssetPathToGUID(string path) : 參數path,是資產的文件系統路徑。
GUI.Button:做一個按鈕。用戶單擊它們就會立即發生一些事情。Button(Rect position, string text):第一個參數是:屏幕上用於按鈕的矩形; 第二個參數是:文本顯示在按鈕上。
● 注意: 在方法前 添加 “ [InitializeOnLoadMethod] ” 表示此方法會在 C# 代碼每次編譯完成後首先調用。 監聽 “ EditorApplication.projectWindowItemOnGUI ” 的委託, 即可使用 GUI 的方法繪製自定義的 UI 元素。
●InitializeOnLoadMethod:允許在Unity加載時初始化編輯器類方法,而無需用戶的操作。
監聽事件 (判斷當移動一個文件時是否合法)
● 我們可以通過監聽資源的創建、刪除、移動、和保存事件 來創建程序,然後約束資源, 這樣資源就不會很凌亂。
● 例如,將某個文件移動到錯誤的目錄下,此時就可以監聽資源移動事件,程序判斷資源的原始位置以及將要
移動的位置是否合法,從而決定是否能阻止本次移動。 Unity 提供了監聽的基類。
如下代碼所示:需要繼承UnityEditor.AssetModificationProcessor,接着重寫監聽資源創建、刪除、移動和保存的方法,處理自己的特殊邏輯。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_04 : UnityEditor.AssetModificationProcessor
{
[InitializeOnLoadMethod]
static void InitializeOnLoadMethod()
{
全局監聽Project視圖下的資源是否發生變化(添加、刪除、移動)
EditorApplication.projectChanged += delegate ()
{
Debug.Log("change");
};
}
監聽雙擊鼠標左鍵打開資源事件
public static bool IsOpenForEdit(string assetPath, out string message)
{
message = null;
Debug.LogFormat("assetPath : {0} ", assetPath);
true表示該資源可以打開,false表示不允許在unity中打開該資源
return false;
}
監聽資源即將被創建事件
public static void onWillCreateAsset(string path)
{
Debug.LogFormat("path : {0}", path);
}
監聽資源即將被保存事件
public static string[] OnWillSaveAssets(string[] paths)
{
if(paths != null)
{
Debug.LogFormat("path : {0}", string.Join(",", paths));
}
return paths;
}
監聽資源即將被移動事件
public static AssetMoveResult OnWillMoveAsset(string oldPath,string newPaht)
{
Debug.LogFormat("from :{0} to : {1}", oldPath, newPaht);
//AssetMoveResult.DidMove表示該資源可以移動
return AssetMoveResult.DidMove;
}
監聽資源即將被刪除事件
public static AssetDeleteResult OnWillDeleteAsset(string assetPath,RemoveAssetOptions option)
{
Debug.LogFormat("delete : {0}", assetPath);
AssetDeleteResult.DidNotDelete表示該資源可以被刪除
return AssetDeleteResult.DidDelete;
}
}
InitializeOnLoadMethod:允許在Unity加載時初始化編輯器類方法,而無需用戶的操作。
Debug.LogFormat(string, Object []):該函數的功能是 將格式化的消息記錄到Unity控制檯,第一個參數是包含在 “ ” 中的文本, 第二個參數是 要輸出的 遊戲對象
Debug.Log(): 將消息記錄到Unity控制檯.
string.Join() : 將數組的內容連接成一個字符串。元素由
seperator
字符串分隔並返回連接數組的副本。AssetMoveResult.DidMove : 告訴內部實現,腳本在磁盤上物理移動了資產。
AssetMoveResult.DidMove : 告訴內部實現腳本將資產實際移動到磁盤上。
AssetMoveResult() : 監聽資源即將被移動事件的函數。
AssetDeleteResult() : 監聽資源即將被刪除事件。
RemoveAssetOptions : 刪除資源的選項。
AssetDeleteResult.DidDelete : 告訴Unity資產已被回調刪除。unity不會嘗試刪除資產,但會刪除緩存版本和預覽文件。
擴展Hierarch 視圖中的 Create 菜單選項
● 在Hierarch 視圖中可以創建所有的遊戲對象(遊戲對象由遊戲資源組成,遊戲場景由若干的遊戲對象組成),Project 視圖中可以管理所有的遊戲資源。 那也不是所有的資源都可以直接拖入 Hierarch 視圖中, 通常只有遊戲對象才能放進。
● 在 Hierarchy 視圖中,也可以對 Create 菜單項進行拓展。如圖 所示,在 Hierarchy 視圖中點擊 Create 按鈕,彈出的菜單 My Create→Cube 就是自定義拓展的菜單,代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_05
{
[MenuItem("GameObject/My Create/Cube",false,0)]
static void CreateCube()
{
GameObject.CreatePrimitive(PrimitiveType.Cube); 創建立方體
}
}
● GameObject.CreatePrimitive (PrimitiveType. Type) 方法用於創建 Unity 基礎原始遊戲對象;
參數Type表示要創建的原始對象的類型。
● MenuItem 方法: 第一個參數是要創建的菜單路徑,第二個是false, 第三個是菜單條的排序,越小越在前面。
● 菜單中已經包含了系統默認的一些菜單項,我們拓展的原理就是重寫 MenuItem 的自定義路徑。 Create 按鈕下的菜單項都在 GameObject 路徑下面,所以只要開頭是 GameObject/xx/xx,均可自由拓展。
擴展布局(點擊Hierarch中的遊戲對象在右側擴展出一組按鈕 )
● 選擇不同的遊戲對象後,在右側可根據 EditorGUI 拓展出一組按鈕,點擊 Unity 圖標按鈕後,在 Console 窗口中輸入這個
遊戲對象。它的工作原理就是監聽 EditorApplication.hierarchyWindowItemOnGUI 渲染回調。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_06
{
[InitializeOnLoadMethod]
static void InitializeOnLoadMethod()
{
EditorApplication.hierarchyWindowItemOnGUI = delegate (int instanceID, Rect selectionRect) {
在Hierarchy視圖中選擇一個資源
if (Selection.activeObject &&
instanceID == Selection.activeObject.GetInstanceID())
{
設置拓展按鈕區域
float width = 50f;
float height = 20f;
selectionRect.x += (selectionRect.width - width);
selectionRect.width = width;
selectionRect.height = height;
點擊事件
if (GUI.Button(selectionRect, AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png")))
{
Debug.LogFormat("click : {0}", Selection.activeObject.name);
}
}
};
}
}
● 在代碼中實現 EditorApplication.hierarchyWindowItemOnGUI 委託,就可以重寫Hierarchy 視圖了。這裏我們使用 GUI.Button 來繪製自定義按鈕,點擊按鈕可監聽事件。
● 在VS中保存代碼後, 在Unity 中的 hierarch 視圖中的 遊戲對象就有一個小按鈕了, 點擊這個按鈕,就可以在 Console 中輸出這個遊戲對象的日誌了。
Object.GetInstanceID: 返回實例對象的ID
Button(Rect position, GUIContent content): 第一個參數爲:屏幕上用於按鈕的矩形, 第二個參數爲:該按鈕的文本、圖像和工具提示。返回結果爲: 當用戶單擊按鈕時爲真。
AssetDatabase.LoadAssetAtPath(string assetPath, Type type):第一個參數爲:資源的加載路徑, 第二個參數爲:資源的加載類型
重寫菜單(重寫Hierarch 視圖中的菜單,完全使用資金的菜單)
● 通過上面的學習,我們知道 Hierarchy 視圖中的菜單可以在原有基礎上拓展,那麼如果想徹底拋棄它的菜單項,完全使用自己的菜單項是否可行呢?答案是可行的。如圖 3-8 所示,先用鼠標選擇一個遊戲對象,點擊右鍵即可彈出我們的重寫菜單,這個菜單項已經和 Unity 自帶的完全不一樣了。它的工作原理就是監聽點擊的事件,打開一個新的菜單窗口。相關代碼如下所示:
下面看示例代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_07
{
[MenuItem("Window/Test/HuangChengTao")]
static void Test()
{
}
[MenuItem("Window/Test/ManNiu")]
static void Test1()
{
}
[MenuItem("Window/Test/濤水/TAOSHUI")]
static void Test2()
{
}
[InitializeOnLoadMethod] 允許在Unity加載時初始化一個編輯器類方法,而不需要用戶的操作。
static void StartInitializeOnLoadMethod()
{
EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
}
static void OnHierarchyGUI(int instanceID,Rect selectionRect)
{
if (Event.current != null && selectionRect.Contains(Event.current.mousePosition)
&& Event.current.button == 1 && Event.current.type <= EventType.MouseUp)
{
GameObject selectedGameObject = EditorUtility.InstanceIDToObject(instanceID)
as GameObject;
這裏可以判斷 selectedGameObject 的條件
if(selectedGameObject)
{
Vector2 mousePosition = Event.current.mousePosition;
EditorUtility.DisplayPopupMenu(new Rect(mousePosition.x,mousePosition.y, 0, 0), "Window/Test", null);
Event.current.Use();
}
}
}
}
EditorApplication.hierarchyWindowItemOnGUI : 在hierarchy窗口中爲每個可見列表項委託GUI事件。
Event.current : 獲取當前正在處理的事件
Rect.Contains:如果點的x和y分量是該矩形內的點,則返回true。 如果允許反相存在且爲真,則允許矩形的寬度和高度取負值(即最小值大於最大值),並且測試仍然有效。參數point: 測試的點,參數allowInverse:測試是否允許矩形的寬度和高度爲負值?返回結果: 如果點位於指定的矩形內,則爲真。
Event.mousePosition : 用於判斷鼠標的位置。 用於EventType.MouseMove 和 EventType.MouseDrag事件。
Event.button : 表示哪個鼠標按鈕被按下了。 0表示鼠標左鍵, 1 表示鼠標右鍵, 2 表示鼠標中鍵,用於EventType.Mousedown和EventType.MouseUp事件。
Event.type:表示事件的類型。
EventType.MouseUp : 鼠標按鈕被鬆開了。 鬆開任何鼠標按鈕時,都會發送此事件。使用 Event.button來確定按下了哪個按鈕。
InstanceIDToObject: 將實例ID轉換爲對象的引用。參數是: instanceID:
EditorUtility: 編寫實用的功能。
Vector2 : 用給定的x, y分量構造一個新的向量。
DisplayPopupMenu : 顯示彈出菜單。參數是: position、menu Item Path、command 。
Rect: 創建一個新矩形. 參數x: 計算矩形的X值。 參數y: 計算矩形的y值。參數width: 矩形的寬度。 參數height: 參數的高度。
Event.current.Use() : 使用此事件, 表示不再執行原有的操作, 所以就實現了重寫菜單。
此外, Hierarchy 視圖還可以重寫系統自帶的菜單行爲。例如,我覺得 Unity 創建的 Image 組件不好,可以複寫它的行爲,如圖所示:
創建 Image 組件時,會自動勾選 RaycastTarget。如果圖片不需要處理點擊事件,這樣會帶來一些額外的開銷。以下代碼就是複寫了創建 Image 組件的邏輯,讓 RaycastTarget 默認不勾選。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
public class Script_03_08
{
[MenuItem("GameObject/UI/Image")]
static void CreateImage()
{
if(Selection.activeTransform)
{
if(Selection.activeTransform.GetComponentInParent<Canvas>())
{
Image image = new GameObject("image").AddComponent<Image>();
image.raycastTarget = false;
image.transform.SetParent(Selection.activeTransform, false);
//設置選中狀態
Selection.activeTransform = image.transform;
}
}
}
}
由於重寫了菜單,所以需要通過腳本自行創建 Image 對象和組件。接着,獲取到 image 組件對象,直接設置它的 raycastTarget 屬性即可。
GameObject.GetComponentInParent : 在GameObject 中 或者 其它父類型中 返回類型的組件。向上遞歸直到找到一個有效的組件。如果沒有找到組件,返回null。只返回GameObject上的組件
拓展 Inspector 視圖(擴展源生組件——攝像機)
● 可以在攝像機組件的最上面添加一個按鈕。它的侷限性就是拓展組件只能加在源生組件的最上面或者最下面,不能插在中間。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Camera))]
public class Script_03_09 : Editor
{
public override void OnInspectorGUI()
{
if(GUILayout.Button("擴展按鈕"))
{
}
base.OnInspectorGUI(); //實現此功能以創建自定義的Inspector
}
}
CustomEditor()表示自定義哪個組件, OnInspectorGUI()可以對它進行重新繪製, base.OnInspectorGUI()表示是否繪製父類原有元素。
GUILayout.Button : 在按鈕上顯示文字。
拓展繼承組件(擴展Transform 組件)
● Unity 將大量的 Editor 繪製方法封裝在內部的 DLL 文件裏,開發者無法調用它的方法。如果想解決這個問題,可以使用 C# 反射的方式調用內部未公開的方法。如圖 所示,通過拓展的Transfom 組件,現在就可以保留原有的繪製方式了。
● 首先通過反射先得到 UnityEditor.TransformInspector 對象,然後就可以調用它內部的 OnInspectorGUI()方法了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(Transform))]
public class Script_03_10 : Editor
{
private Editor m_Editor;
private void OnEnable()
{
m_Editor = Editor.CreateEditor(target,
Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true));
}
public override void OnInspectorGUI()
{
//調用系統繪製方法
m_Editor.OnInspectorGUI();
//base.OnInspectorGUI();
}
}
Editor :派生自定義編輯器的基類。使用它爲對象創建自己的自定義Inspector和編輯器。
CreateEditor : 爲 targetObject 或 targetObjects 創建自定義編輯器。參數Object——所有對象必須具有相同的類型。
OnInspectorGUI(): 實現此函數以生成自定義的Inspector.
● 上述代碼中,我們重寫了 OnInspectorGUI()方法。使用 GUILayout.Button 繪製了自定義的按鈕元素,接着調用 m_Editor.OnInspectorGUI()繪製 Transform 原有面板信息,這樣我們拓展的按鈕就會顯示在 Transform 面板的上方。
就像下面這樣:
組件不可以編輯 (禁掉某個組件,使它無法編輯)
● 在 Unity 中,我們可以給組件設置狀態,這樣它就無法編輯了。如圖所示,將 Transform組件的原始功能禁掉(灰色表示不可編輯),而不影響我們上下拓展的兩個按鈕。代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(Transform))]
public class Script_03_11 : Editor
{
private Editor m_Editor;
private void OnEnable()
{
m_Editor = Editor.CreateEditor(target,
Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor." +
"TransformInspector", true));
}
public override void OnInspectorGUI()
{
if(GUILayout.Button("擴展按鈕上"))
{
}
// 開始禁止
GUI.enabled = false;
m_Editor.OnInspectorGUI();
//結束禁止
GUI.enabled = true;
if (GUILayout.Button("擴展按鈕下"))
{
}
}
}
● 如果想整體禁止組件,可以按照圖所示選擇任意遊戲對象,然後從右鍵菜單中選擇 3DObject→Lock→Lock(鎖定)或者 UnLock(解鎖)。它的原理就是設置遊戲對象的 hideFlags。需要說明的是,我們不一定非設置遊戲對象的 hideFlags,也可以單獨給某個組件設置hideFlags,這樣只會影響到某一個組件並非全部。相關代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_12
{
[MenuItem("GameObject/3D object/Lock/lock",false,0)]
static void Lock()
{
if(Selection.gameObjects!=null)
{
foreach(var gameObject in Selection.gameObjects)
{
gameObject.hideFlags = HideFlags.NotEditable;
}
}
}
[MenuItem("GameObject/3D object/Lock/UnLok",false,1)]
static void UnLock()
{
if(Selection.gameObjects!=null)
{
foreach(var gameObject in Selection.gameObjects)
{
gameObject.hideFlags = HideFlags.None;
}
}
}
}
HideFlags 可以使用按位或(|)同時保持多個屬性,其含義都很好理解,大家可以自行輸入代碼調試一下。
HideFlags.None: 解除狀態。
HideFlags.DontSave: 設置對象不會被保存(僅編輯模式下使用,運行時剔除掉)。
HideFlags.DontSaveInBuild: 設置對象構建後不會被保存。
HideFlags.DontSaveInEditor: 設置對象編輯模式下不會被保存。
HideFlags.DontUnloadUnusedAsset: 設置對象不會被 Resources.UnloadUnusedAssets()卸載無用資源時卸掉。
HideFlags.HideAndDontSave: 設置對象隱藏,並且不會被保存。
HideFlags.HideInHierarchy: 設置對象在層次視圖中隱藏。
HideFlags.HideInInspector: 設置對象在控制面板視圖中隱藏。
HideFlags.NotEditable: 設置對象不可被編輯。
Selection.gameObjects——選擇返回實際的遊戲對象。包括prefab,不可修改的對象。當處理場景中主要的對象時,強烈建議使用Selection.transforms。
Selection —— 訪問編輯器中的選定內容。
Context 菜單
● 點擊組件中設置(鼠標右鍵),可以彈出 Context 菜單,如圖所示,我們可在原有菜單中拓展出新的菜單欄,相關代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Script_03_13
{
[MenuItem("CONTEXT/Transform/ New Context 1")]
public static void NewContext1(MenuCommand command)
{
//獲取對象名
Debug.Log(command.context.name);
}
[MenuItem("CONTEXT/Transform/New Context 2")]
public static void NewContext2(MenuCommand command)
{
Debug.Log(command.context.name);
}
}
MenuCommand——用於提取MenuItem的上下文。MenuCommand對象被傳遞給使用MenuItem屬性定義的自定義菜單項函數。
注意:菜單項被添加到對象中,並且可以通過Inspector中的右擊來訪問。 腳本代碼需要CONTEXT選項。
MenuCommand.context——Context是菜單命令的目標對象。
其中, [MenuItem("CONTEXT/Transform/New Context 1")] 表示將新菜單擴展在Transform 組件上。如果想拓展在別的組件上,例如攝像機組件,直接修改字符串中的 Transform爲 Camera 即可。如果想給所有組件都添加菜單欄,這裏改成 Compoment 即可。
以上設置也可以應用在自己寫的腳本中。如圖 ,Script_03_14Component.cs 是自己創建的腳本,在代碼中可以通過 MenuCommand 來獲取腳本對象,從而訪問腳本中的變量,相關代碼下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class Script_03_14Component: MonoBehaviour
{
public string contextName;
#if UNITY_EDITOR
[MenuItem("CONTEXT/Script_03_14/NewTTContext 1")]
public static void NewContext2(MenuCommand command)
{
Script_03_14 script = (command.context as Script_03_14);
script.contextName = "hello world!!";
}
#endif
}
注意: 在該腳本中繼承了MonoBehaviour類, 表示我們應該要在Script 文件夾中創建腳本,而不是在Editor中創建腳本,編輯好腳本後,保存。 然後鼠標左鍵拖到Hierarch 中的某一個遊戲對象上去。
MonoBehaviour是每個Unity腳本派生的基類。
MenuCommand 是獲取腳本對象。
ContextMenu —— ContextMenu屬性允許你向Context菜單添加指令。設置該功能的函數必須是靜態的。
在上述代碼中,我們使用到了宏定義標籤,其中UNITY_EDITOR 表示這段代碼只會在Editor模式下執行,發佈後將被剔除掉。
看我們擴展後的結果:
當然,我們也可以在自己的腳本中這樣寫。如果和系統的菜單項名稱一樣,還可以覆蓋它。比如,這裏重寫了刪除組件的按鈕,就可以執行一些自己的操作了:
[ContextMenu("Remove Component")]
void RemoveComponent()
{
Debug.Log("RemoveComponent");
//等一幀再刪除自己
UnityEditor.EditorApplication.delayCall = delegate() {
DestroyImmediate(this);
};
}
編輯模式下的代碼同步時有可能會有問題,比如上述 DestroyImmediate(this)刪除自己的代碼時,會觸發引擎底層的一個錯誤。不過我們可以使用 UnityEditor.EditorApplication.delayCall 來延遲一幀調用。後續如果大家在開發編輯器代碼時發現類似問題,也可以嘗試等
一幀再執行自己的代碼。
後續在這篇文章: 第三章——擴展Unity編輯器2 —— https://blog.csdn.net/qq_34536551/article/details/83793216