关键概念
- [MenuItem(“GameObject/XXX”)] : 创建左上角的 Create 菜单项。如果跟已有的路径相同,将覆盖已有功能。
- EditorApplication.hierarchyWindowItemOnGUI : 委托,处理 hierarchy 窗口对象的绘制。签名:void OnGUI(int instanceID, Rect selectionRect)。
- int instanceID : 选中的 GameObject 的实例 ID 。
- Rect seletctionRect : GameObject 在 Hierarchy 窗口的绘制区域。
- Selection.activeObject : 当前选中的 Object , 包括资源对象,所以可能不是 GameObject
- GameObject.GetInstanceID() : 获取对象的实例 ID。
- AssetDatabase.LoadAssetAtPath(string path) : 从指定路径加载资源
- Event : 编辑器事件。
- Event.current : 当前事件
- Event.current.mousePosition : 事件的鼠标位置
- Event.current.button : 鼠标按键。 0:左键 1:右键 2:中键
- Event.current.type : 事件类型。如:EventType.MouseDown/MouseUp
- int EditorUtility.InstanceIDToObject(int instanceID) : 根据给定的实例 ID 找到Object。
- EditorUtility.DisplayPopupMenu(Rect rect, string menuPath, MenuCommand command) : 显示一个弹出式窗口。
例子
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
public class HierarchyExtend
{
[MenuItem("GameObject/My Create/Create Sphere", false, 0)]
static void CreateSphere()
{
GameObject.CreatePrimitive(PrimitiveType.Sphere);
}
[InitializeOnLoadMethod]
static void InitializeOnLoadMethod()
{
EditorApplication.hierarchyWindowItemOnGUI = OnGUI + EditorApplication.hierarchyWindowItemOnGUI;
}
static void OnGUI(int instanceID, Rect selectionRect)
{
if (Selection.activeGameObject && instanceID == Selection.activeGameObject.GetInstanceID())
{
float width = 50;
float height = 20;
selectionRect.x += selectionRect.width - width;
selectionRect.height = height;
if (GUI.Button(selectionRect, AssetDatabase.LoadAssetAtPath<Texture>("Asset/unity.png")))
{
Debug.Log($"GameObject clicked:{Selection.activeGameObject.name}");
}
}
if (Event.current != null && selectionRect.Contains(Event.current.mousePosition))
{
Debug.Log($"button:{Event.current.button}, type:{Event.current.type}");
if (Event.current.button == 1 && Event.current.type <= EventType.MouseUp)
{
GameObject selectedGameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (selectedGameObject)
{
Vector2 mousePos = Event.current.mousePosition;
EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "Window/Test", null);
Event.current.Use();
}
}
}
}
[MenuItem("Window/Test/A")]
static void A()
{
Debug.Log("run A");
}
[MenuItem("Window/Test/B")]
static void B()
{
Debug.Log("run B");
}
[MenuItem("Window/Test/C/c")]
static void C()
{
Debug.Log("run C");
}
[MenuItem("GameObject/UI/Image")]
static void CreateImage()
{
if(Selection.activeTransform)
{
if(Selection.activeTransform.GetComponentInParent<Canvas>())
{
Image img = new GameObject("image").AddComponent<Image>();
img.raycastTarget = false;
img.transform.SetParent(Selection.activeTransform, false);
Selection.activeTransform = img.transform;
}
}
}
}