效果图:
上图中在Hierarchy右侧绘制了Toggle,Label,以及自定义的texture和Unity原声的Texture,知道了原理,其实这些都很简单。。
这里主要是使用了EditorApplication类下的HierarchyWindowItemCallback类型的hierarchyWindowItemOnGUI
//
// 摘要:
// ///
// Delegate to be called for every visible list item in the HierarchyWindow on every
// OnGUI event.
// ///
//
// 参数:
// instanceID:
//
// selectionRect:
public delegate void HierarchyWindowItemCallback(int instanceID, Rect selectionRect);
该委托有两个参数,一个是int类型的instanceID,通过该ID利用EditorUtility.InstanceIDToObject(instanceID)可以获取该GameObject,然后第二个参数Rect,也就是该物体在Hierarchy面板的位置信息了,通过这两个数据,在Hierarchy面板上拓展就很简单了。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
[InitializeOnLoad]
public class HierachyIconManager
{
// 层级窗口项回调
private static readonly EditorApplication.HierarchyWindowItemCallback hiearchyItemCallback;
private static Texture2D hierarchyIcon;
private static Texture2D HierarchyIcon
{
get
{
if (HierachyIconManager.hierarchyIcon == null)
{
HierachyIconManager.hierarchyIcon = (Texture2D)Resources.Load("icon_1");
}
return HierachyIconManager.hierarchyIcon;
}
}
/// <summary>
/// 静态构造
/// </summary>
static HierachyIconManager()
{
HierachyIconManager.hiearchyItemCallback = new EditorApplication.HierarchyWindowItemCallback(HierachyIconManager.DrawHierarchyIcon);
EditorApplication.hierarchyWindowItemOnGUI = (EditorApplication.HierarchyWindowItemCallback)Delegate.Combine(
EditorApplication.hierarchyWindowItemOnGUI,
HierachyIconManager.hiearchyItemCallback);
//EditorApplication.update += Update;
}
// 绘制icon方法
private static void DrawHierarchyIcon(int instanceID, Rect selectionRect)
{
Rect rectCheck = new Rect(selectionRect);
rectCheck.x += rectCheck.width - 20;
rectCheck.width = 18;
GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
go.SetActive(GUI.Toggle(rectCheck, go.activeSelf, string.Empty));
var index = 0;
GUIStyle style = null;
if (go.isStatic)
{
index += 1;
Rect rectIcon = GetRect(selectionRect, index);
GUI.Label(rectIcon, "S");
}
// 文字颜色定义
var colorMesh = new Color(42 / 255f, 210 / 255f, 235 / 255f);
var colorSkinMesh = new Color(0.78f, 0.35f, 0.78f);
var colorLight = new Color(251 / 255f, 244 / 255f, 124 / 255f);
var colorPhysic = new Color(0.35f, 0.75f, 0f);
var colorCollider = new Color(0.35f, 0.75f, 0.196f);
var colorAnimation = new Color(175 / 255f, 175 / 255f, 218 / 255f);
var colorCamera = new Color(111 / 255f, 121 / 255f, 212 / 255f);
var colorParticle = new Color(130 / 255f, 124 / 255f, 251 / 255f);
var colorNav = new Color(217 / 255f, 80 / 255f, 62 / 255f);
var colorNetwork = new Color(42 / 255f, 129 / 255f, 235 / 255f);
var colorAudio = new Color(255 / 255f, 126 / 255f, 0f);
DrawRectIcon(selectionRect,HierarchyIcon,ref index);
DrawRectIcon<MeshRenderer>(selectionRect, go, colorMesh, ref index, ref style);
DrawRectIcon<SkinnedMeshRenderer>(selectionRect, go, colorSkinMesh, ref index, ref style);
// Colliders
DrawRectIcon<BoxCollider>(selectionRect, go, colorCollider, ref index, ref style);
DrawRectIcon<SphereCollider>(selectionRect, go, colorCollider, ref index, ref style);
DrawRectIcon<CapsuleCollider>(selectionRect, go, colorCollider, ref index, ref style);
DrawRectIcon<MeshCollider>(selectionRect, go, colorCollider, ref index, ref style);
DrawRectIcon<CharacterController>(selectionRect, go, colorCollider, ref index, ref style);
// RigidBody
DrawRectIcon<Rigidbody>(selectionRect, go, colorPhysic, ref index, ref style);
// Lights
DrawRectIcon<Light>(selectionRect, go, colorLight, ref index, ref style);
// Joints
// Animation / Animator
DrawRectIcon<Animator>(selectionRect, go, colorAnimation, ref index, ref style);
DrawRectIcon<Animation>(selectionRect, go, colorAnimation, ref index, ref style);
// Camera / Projector
DrawRectIcon<Camera>(selectionRect, go, colorCamera, ref index, ref style);
DrawRectIcon<Projector>(selectionRect, go, colorCamera, ref index, ref style);
// NavAgent
DrawRectIcon<UnityEngine.AI.NavMeshAgent>(selectionRect, go, colorNav, ref index, ref style);
DrawRectIcon<UnityEngine.AI.NavMeshObstacle>(selectionRect, go, colorNav, ref index, ref style);
// Network
DrawRectIcon<NetworkIdentity>(selectionRect, go, colorNetwork, ref index, ref style);
DrawRectIcon<NetworkAnimator>(selectionRect, go, colorNetwork, ref index, ref style);
DrawRectIcon<NetworkTransform>(selectionRect, go, colorNetwork, ref index, ref style);
DrawRectIcon<NetworkBehaviour>(selectionRect, go, colorNetwork, ref index, ref style);
DrawRectIcon<NetworkManager>(selectionRect, go, colorNetwork, ref index, ref style);
// Particle
DrawRectIcon<ParticleSystem>(selectionRect, go, colorParticle, ref index, ref style);
// Audio
DrawRectIcon<AudioSource>(selectionRect, go, colorAudio, ref index, ref style);
DrawRectIcon<AudioReverbZone>(selectionRect, go, colorAudio, ref index, ref style);
//UI
DrawRectIcon<Image>(selectionRect, go, colorParticle, ref index, ref style);
DrawRectIcon<Text>(selectionRect, go, colorParticle, ref index, ref style);
DrawRectIcon<SpriteRenderer>(selectionRect, go, colorParticle, ref index, ref style);
// 绘制Label来覆盖原有的名字
if (style != null && go.activeInHierarchy)
{
GUI.Label(selectionRect, go.name, style);
}
}
private static void Update()
{
Debug.Log("1");
}
private static Rect GetRect(Rect selectionRect , int index)
{
Rect rect = new Rect(selectionRect);
rect.x += rect.width - 20 - (20 * index);
rect.width = 18;
return rect;
}
/// <summary>
/// 绘制一个Unity原声图标
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="rect"></param>
private static void DrawIcon<T>(Rect rect)
{
var icon = EditorGUIUtility.ObjectContent(null, typeof(T)).image;
GUI.Label(rect, icon);
}
private static void DrawRectIcon<T>(Rect selectionRect,GameObject go,Color textColor,ref int order, ref GUIStyle style)where T :Component
{
if (go.HasComponent<T>())
{
order += 1;
var rect = GetRect(selectionRect, order);
DrawIcon<T>(rect);
}
}
private static void DrawRectIcon(Rect selectionRect,Texture2D texture,ref int order)
{
order += 1;
var rect = GetRect(selectionRect,order);
GUI.Label(rect,texture);
}
}
public static class ExtensionMethods
{
public static bool HasComponent<T>(this GameObject go) where T : Component
{
return go.GetComponent<T>() != null;
}
}
其中使用了[InitializeOnLoad],这个Attribute的意思是在启动Unity的时候运行的编辑器脚本,该类需要一个静态的构造函数。。
通过EditorGUIUtility.ObjectContent(null, typeof(T)).image就可以获取到T类型的Unity原声Texture了。
而Label和Toggle,则分别使用GUI.Label和GUI.Toggle即可。。具体参见上面代码。
我们可以根据需要定制自己需要的Hierarchy面板,例如上述代码中通过判断该GameObject是否是static的,如果是,则绘制一个S在旁边,这样就可以很快速的查看哪些物体是static的了。。
以上知识分享,如有错误,欢迎指出,共同学习,共同进步