当前位置: 首页 > news >正文

【第四章自定义编辑器窗口_扩展默认的编辑器窗口_扩展Hierarchy窗口(7/11)】

4.2 如何扩扩展默认的编辑器窗口

4.2.1 扩展Hierarchy窗口

using UnityEditor;
using UnityEngine;// 自定义Hierarchy窗口扩展类
public class CustomHierarchyWindow
{// InitializeOnLoadMethod特性表示这个方法在Unity编辑器启动或重新编译后自动执行[InitializeOnLoadMethod]static void InitializeOnLoad(){// 安全移除旧的事件监听器(防止重复注册)EditorApplication.hierarchyWindowItemOnGUI-= OnHierarchyWindowItemGUI;// 注册新的事件监听器EditorApplication.hierarchyWindowItemOnGUI+= OnHierarchyWindowItemGUI;}// Hierarchy窗口中每个项目的GUI绘制回调函数private static void OnHierarchyWindowItemGUI(int instanceID,    // Unity对象的唯一实例IDRect selectionRect) // 当前项在Hierarchy窗口中的绘制矩形{// 通过实例ID查找对应的游戏对象GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;// 如果找不到对应的游戏对象则退出if (go == null)return;// 获取该游戏对象上的所有组件Component[] components = go.GetComponents<Component>();// 遍历所有组件for (int i = 0; i < components.Length; i++){Component component = components[i];// 如果组件丢失(如脚本被删除),则跳过if (component == null)continue;// 获取组件的图标:// 1. 先尝试获取该类型的内置小图标// 2. 如果没有,则获取组件的缩略图Texture texture = AssetPreview.GetMiniTypeThumbnail(component.GetType()) ??AssetPreview.GetMiniThumbnail(component);// 如果没有可用的图标,则跳过if (texture == null)continue;// 计算图标位置(从Hierarchy项右侧从右向左排列)Rect rect = selectionRect;rect.x += selectionRect.width - (i + 1) * 20f; // 每个图标间隔20像素rect.width = 20f; // 图标宽度固定为20像素// 绘制组件图标并设置工具提示为组件类型名称GUI.Label(rect, new GUIContent(texture,component.GetType().Name));}}
}

代码功能详解

1. 初始化机制

[InitializeOnLoadMethod]
static void InitializeOnLoad()
{// 安全移除旧的事件监听(防止多次注册)EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemGUI;// 注册新的事件监听EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemGUI;
}
  • [InitializeOnLoadMethod] 特性:使方法在以下情况自动执行:
    • Unity 编辑器启动时
    • 脚本重新编译后
  • 事件注册:订阅 hierarchyWindowItemOnGUI 事件
    • 该事件在 Hierarchy 窗口绘制每个项目时触发
    • 安全移除旧监听防止重复注册

2. 核心绘制函数

private static void OnHierarchyWindowItemGUI(int instanceID,    // Unity内部对象标识符Rect selectionRect) // 当前项的矩形位置
{// 1. 从ID获取实际游戏对象GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;// 2. 有效性检查if (go == null) return;// 3. 获取对象的所有组件Component[] components = go.GetComponents<Component>();// 4. 遍历所有组件for (int i = 0; i < components.Length; i++){Component component = components[i];// 跳过丢失的脚本(组件为空)if (component == null) continue;// 5. 获取组件图标(详见下文)Texture texture = GetComponentIcon(component);if (texture == null) continue;// 6. 计算位置并绘制图标Rect iconRect = CalculateIconRect(selectionRect, i);GUI.Label(iconRect, new GUIContent(texture, component.GetType().Name));}
}

3. 图标获取逻辑

Texture GetComponentIcon(Component component)
{// 1. 先获取类型专用图标(如Camera、Light等内置图标)Texture typeIcon = AssetPreview.GetMiniTypeThumbnail(component.GetType());// 2. 如果没有类型图标,获取组件的缩略图(自定义脚本图标)if (typeIcon == null) {typeIcon = AssetPreview.GetMiniThumbnail(component);}return typeIcon;
}

4. 图标位置计算

Rect CalculateIconRect(Rect baseRect, int index)
{Rect rect = baseRect;// 从右侧开始排列// - 20px * (index + 1) 确保从左向右顺序排列rect.x += baseRect.width - (index + 1) * 20f;// 固定宽度20像素rect.width = 20f;return rect;
}

5. 图标显示效果

在 Hierarchy 窗口中显示:

[游戏对象名称]          [图标3] [图标2] [图标1]
  • 图标顺序:组件添加顺序从右向左排列
  • 悬停提示:鼠标悬停时显示组件类型名
  • 自动跳过
    • 丢失的脚本(组件为null)
    • 没有可用图标的组件

使用效果示例

场景中的显示效果:

在这里插入图片描述

用处

  1. 组件可视化

    • 直观展示对象上所有组件
    • 无需展开查看Inspector
  2. 脚本丢失检测

    • 脚本丢失时图标不显示
    • 快速发现损坏的对象
  3. 快速识别

    • 特殊图标表示特定组件
    • 悬停提示显示具体类型名
  4. 顺序指示

    • 图标排列顺序反映组件添加顺序
    • 帮助理解对象结构

使用注意事项

  1. 性能影响

    • 大型场景中可能会影响编辑器性能
    • 建议添加显示对象数量阈值
  2. 兼容性

    • 只兼容 2018.3+ 版本的 Unity
    • 旧版本 Unity 需要使用其他方法
http://www.dtcms.com/a/303775.html

相关文章:

  • QT项目 -仿QQ音乐的音乐播放器(第三节)
  • 深入理解 Qt 元对象系统 (Meta-Object System)
  • WindowsAPI|每天了解几个winAPI接口之网络配置相关文档Iphlpapi.h详细分析六
  • [明道云]-基础教学2-工作表字段 vs 控件:选哪种?
  • HTTP 与 HTTPS 的区别
  • mapbox进阶,mapbox-gl-draw绘图插件扩展,编辑模式支持点、线、面的捕捉
  • Objective-c 初阶——异常处理(try-catch)
  • 盛最多水的容器-双指针
  • 注册发送手机短信
  • bash变量名不能有连字符
  • Spark初探:揭秘速度优势与生态融合实践
  • RabbitMQ面试精讲 Day 7:消息持久化与过期策略
  • H.264视频的RTP有效载荷格式(翻译自:RFC6184 第5节 RTP有效载荷格式)
  • 网络协议——MPLS(多协议标签转发)
  • 力扣30 天 Pandas 挑战(3)---数据操作
  • LeetCode 283 - 移动零
  • CTF-Web学习笔记:服务端请求伪造(SSRF)篇
  • 单片机学习笔记.PWM
  • 第4章唯一ID生成器——4.5 美团点评开源方案Leaf
  • 医疗AI新基建:MCP与A2A协议的破局与前瞻
  • JVM 崩溃(Fatal Error)解决方法
  • 影刀RPA_初级课程_玩转影刀自动化_EXCEL操作自动化
  • 《C++初阶之STL》【list容器:详解 + 实现】
  • JSON解析
  • Spring IOC 基于Cglib实现含构造函数的类实例化策略
  • 循环神经网络——动手学深度学习7
  • 板凳-------Mysql cookbook学习 (十二--------7)
  • SpringBoot 的@Repository 等注解的底层实现原理
  • 智能体安全与可信AI:防护机制与伦理考量
  • SpringBoot之起步依赖