1. 程式人生 > >Unity編輯器拓展之三:拓展Unity的Hierarchy面板

Unity編輯器拓展之三:拓展Unity的Hierarchy面板

效果圖:

這裡寫圖片描述

上圖中在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的了。。

以上知識分享,如有錯誤,歡迎指出,共同學習,共同進步