Unity编辑器界面扩展——5、Hierarchy栏UI扩展

  大家好,我是阿赵。继续介绍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的时候再获取,诸如此类,各位有兴趣可以自己发挥一下。