大家好,我是阿赵。继续介绍Unity编辑器界面扩展。
之前介绍过怎样修改Inspector栏的UI,不过Inspector栏是需要选中了某个对象之后,才会显示出来的。如果想很快的在场景对象列表里面就能看到某些信息,或者进行某些操作,其实可以扩展Hierarchy栏的显示来做到:
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class HierarchyUIEditor
{
static HierarchyUIEditor()
{
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
EditorApplication.hierarchyChanged += HierarchyChanged;
}
/// <summary>
/// 绘制Hierarchy栏对应物体的UI
/// </summary>
/// <param name="instanceID"></param>
/// <param name="selectionRect"></param>
static void HierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
{
GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (go == null)
{
return;
}
//需要的UI显示写在这里
}
/// <summary>
/// 当Hierarchy栏的对象改变时回调
/// </summary>
static void HierarchyChanged()
{
Debug.Log("HierarchyChanged");
}
}
代码同样很简单,由于现在没有写任何实际的内容,所以回到Unity编辑器不会发现有任何的变化。
简单的来说明一下:
1、Hierarchy的UI显示方法
EditorApplication.hierarchyWindowItemOnGUI+= HierarchyWindowItemOnGUI;
在这里把HierarchyWindowItemOnGUI注册到EditorApplication.hierarchyWindowItemOnGUI里面,当Hierarchy需要显示的时候,就会执行HierarchyWindowItemOnGUI方法。
然后在HierarchyWindowItemOnGUI里面,会传入2个参数
1. instanceID
这是当前需要显示的对象的实例id,通过实例id,可以获得当前需要显示的GameObject对象:
GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
2. selectionRect
这是一个Rect显示坐标范围,当一个对象在Hierarchy显示时,我们可以通过这个范围来控制添加的UI的具体坐标。
2、 Hierarchy栏的对象改变回调方法
这个方法也很有用,有很多时候,需要扩展的显示是和场景里面的物体情况有关系的,比如新增一个物体,或者减少一个物体,或者给物体重命名之类的操作,需要修改扩展显示的内容。 这个时候,通过
EditorApplication.hierarchyChanged += HierarchyChanged;
注册了Hierarchy的变化回调方法,就可以在HierarchyChanged里面进行一下刷新数据和显示的操作。
二、 实用小例子
上面介绍了用法,这里再给一个比较实用的小例子看看:
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class HierarchyUIEditor
{
static HierarchyUIEditor()
{
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
EditorApplication.hierarchyChanged += HierarchyChanged;
}
/// <summary>
/// 绘制Hierarchy栏对应物体的UI
/// </summary>
/// <param name="instanceID"></param>
/// <param name="selectionRect"></param>
static void HierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
{
GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (go == null)
{
return;
}
List<string> iconList = GetIconList(go);
if (iconList.Count>0)
{
for(int i = 0;i<iconList.Count;i++)
{
Rect r = new Rect(selectionRect.x + selectionRect.width - 40-20*i, selectionRect.y, 20, selectionRect.height);
EditorGUI.LabelField(r, EditorGUIUtility.IconContent(iconList[i]));
}
}
}
static private List<string> GetIconList(GameObject go)
{
List<string> iconList = new List<string>();
if (go.GetComponent<Camera>() != null)
{
iconList.Add("d_Camera Icon");
}
if (go.GetComponent<AudioListener>() != null)
{
iconList.Add("d_AudioListener Icon");
}
if (go.GetComponent<Light>() != null)
{
iconList.Add("d_SceneViewLighting");
}
if (go.GetComponent<Collider>() != null)
{
iconList.Add("d_BoxCollider Icon");
}
if (go.GetComponent<MonoBehaviour>() != null)
{
iconList.Add("d_cs Script Icon");
}
return iconList;
}
/// <summary>
/// 当Hierarchy栏的对象改变时回调
/// </summary>
static void HierarchyChanged()
{
}
}
保存代码之后,回到Unity编辑器,会发现现在Hierarchy栏里面的对象显示后面会多了一些图标:
这个小工具的作用是找出对象身上有没有摄像机、AudioListener、灯光、碰撞体,如果有,在对象的后面显示对应的图标。这样如果有些组件自己特别的关注,就不需要逐个物体选中来检查,直接在Hierarchy的列表里面就能找到了。
当然这个工具写得很简陋,和之前的SceneView一样,自己可以加一点场景的开关,或者存储一些信息,不需要每次绘制都获取组件,等HierarchyChanged的时候再获取,诸如此类,各位有兴趣可以自己发挥一下。