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的了。。

以上知识分享,如有错误,欢迎指出,共同学习,共同进步

猜你喜欢

转载自blog.csdn.net/qq_26999509/article/details/78006957
今日推荐