Unity編輯器拓展之三:拓展Unity的Hierarchy面板
阿新 • • 發佈:2019-02-14
效果圖:
上圖中在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的了。。
以上知識分享,如有錯誤,歡迎指出,共同學習,共同進步