Unity编辑器扩展之Hierarchy面板扩展

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

Unity编辑器扩展之Hierarchy面板扩展
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 Hierarchy 面板扩展

为初学者节省宝贵的学习时间,避免困惑!


文章目录

  • 一、Hierarchy菜单扩展
    • 1、拓展菜单(GameObject)
    • 2、GenericMenu自定义菜单扩展
  • 二、EditorApplication.hierarchyChanged 之自动重命名重复对象名称
  • 三、EditorApplication.hierarchyWindowItemOnGUI 之布局扩展
    • 1、绘制ActiveToggle
    • 2、绘制Static静态标记
    • 3、绘制组件的Icon
    • 4、重绘对象名称


Hierarchy_47">一、Hierarchy菜单扩展


1、拓展菜单(GameObject)


通过 MenuItem 属性,可以在Hierarchy窗口上下文菜单中将菜单项添加到“GameObject/”菜单

MenuItem 属性能够将任何静态函数转变为菜单命令。仅静态函数可使用 MenuItem 属性。

之前已经写过相关文章:
https://blog.csdn.net/caiprogram123/article/details/133953622#6GameObject_593

2、GenericMenu自定义菜单扩展


当右键点击 Hierarchy 视图中的 GameObject 时,将创建一个包含 “Option 1” 和 “Option 2” 两个选项的 GenericMenu 菜单,并在点击时触发相应的方法。

之前已经写过相关文章:
https://blog.csdn.net/caiprogram123/article/details/135373693#Hierarchy_172



EditorApplicationhierarchyChanged__70">二、EditorApplication.hierarchyChanged 之自动重命名重复对象名称


EditorApplication.hierarchyChanged 是 Unity 编辑器中的一个事件,用于检测和响应场景层级(Hierarchy)中的变化。

当场景中的对象被添加、删除、重命名,或对象的父子关系发生变化时,Unity 会触发 hierarchyChanged 事件。

这使得开发者能够在这些变化发生时执行自定义逻辑,如自动重命名对象、更新层级视图中的图标或状态、同步层级结构与外部数据等。

using UnityEditor;
using UnityEngine;
using System.Linq;public class AutoRenameDuplicateObjects
{[InitializeOnLoadMethod]static void Initialize(){EditorApplication.hierarchyChanged += OnHierarchyChanged;}private static void OnHierarchyChanged(){// 查找场景中的所有对象GameObject[] allObjects = Object.FindObjectsOfType<GameObject>();// 按照父对象分组,检查每个组中是否有重复名称的对象foreach (var parentGroup in allObjects.GroupBy(obj => obj.transform.parent)){if(parentGroup.Count() < 2) continue;// 对同一层级的对象按照Hierarchy中的顺序排序var sortedGroup = parentGroup.OrderBy(obj => obj.transform.GetSiblingIndex()).ToList();var duplicates = sortedGroup.GroupBy(obj => obj.name).Where(group => group.Count() > 1);foreach (var duplicateGroup in duplicates){int index = 1;foreach (GameObject go in duplicateGroup){string newName = $"{go.name}_{index++}";Undo.RecordObject(go, "Auto Rename Duplicate Objects");go.name = newName;EditorUtility.SetDirty(go);Debug.Log($"Renamed {go.name} to {newName}");}}}}
}

通过监听 EditorApplication.hierarchyChanged 事件,当层级结构发生变化时,代码会自动检查是否有同一父对象下的子对象名称重复,并按照从上到下的顺序进行重命名。

在这里插入图片描述



EditorApplicationhierarchyWindowItemOnGUI__133">三、EditorApplication.hierarchyWindowItemOnGUI 之布局扩展


EditorApplication.hierarchyWindowItemOnGUI 是 Unity 编辑器提供的一个事件,用于在 Hierarchy 窗口中绘制自定义的 GUI。

这个事件会在每一帧渲染 Hierarchy 窗口时触发,并为每个可见的层级对象调用一次,允许开发者在 Hierarchy 窗口的每个对象旁边绘制自定义内容,如按钮、图标或文本。

using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using System.Reflection;
using System.Linq;public class HierarchyEditor
{private const float MinWindowWidth = 240f; // 设置显示图标和Toggle的最小窗口宽度// 在加载时初始化[InitializeOnLoadMethod]static void HierarchyExtensionIcon(){var activeStyle = new GUIStyle() { normal = { textColor = Color.green } };var inactiveStyle = new GUIStyle() { normal = { textColor = new Color(0, 1, 0, 0.5F) } };EditorApplication.hierarchyWindowItemOnGUI += (int instanceID, Rect selectionRect) =>{GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;if (go == null) return;int index = 0;//绘制对象激活状态切换按钮DrawActiveToggle(go, selectionRect, ref index);//绘制静态标记DrawStatic(go, selectionRect, ref index);//绘制组件ICONDrawRectIcon<BoxCollider>(go, selectionRect, ref index);//重绘对象名称DrawGameObjectName(go, selectionRect, activeStyle, inactiveStyle);};}// 获取 Hierarchy 窗口的宽度private static float GetHierarchyWindowWidth(){PropertyInfo hierarchyInfo = typeof(Editor).Assembly.GetType("UnityEditor.SceneHierarchyWindow")?.GetProperty("lastInteractedHierarchyWindow", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);EditorWindow hierarchyWindow = (EditorWindow)hierarchyInfo?.GetValue(null);return hierarchyWindow?.position.width ?? 0;}/// <summary>/// 获取Rect/// </summary>private static Rect GetRect(Rect selectionRect, int index){Rect rect = new Rect(selectionRect);if (GetHierarchyWindowWidth() >= MinWindowWidth){rect.x += rect.width - (18 * index);}else{rect.x += rect.width + (18 * index);}rect.width = 18;return rect;}
}

1、绘制ActiveToggle


为每个对象绘制一个激活状态的 Toggle 按钮,允许用户直接在 Hierarchy 窗口中切换对象的激活状态。

/// <summary>
/// 绘制激活状态的Toggle按钮
/// </summary>
private static void DrawActiveToggle(GameObject go, Rect selectionRect, ref int index)
{index++;Rect rect = GetRect(selectionRect, index);bool currentActiveState = go.activeSelf;// 检查鼠标是否在当前对象的 ActiveToggle 区域内if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)){// 获取选中的所有对象GameObject[] selectedObjects = Selection.gameObjects;// 如果未选中对象,则只更改当前对象的状态if (!selectedObjects.Contains(go)){Selection.activeGameObject = go;selectedObjects = new GameObject[] { go };}bool newActiveState = !currentActiveState;Undo.RecordObjects(selectedObjects, "Toggle Active State");foreach (GameObject selectedObject in selectedObjects){selectedObject.SetActive(newActiveState);}EditorSceneManager.MarkAllScenesDirty();Event.current.Use(); // 使用事件,避免被传递}GUI.Toggle(rect, currentActiveState, string.Empty);
}

如果用户改变了对象的激活状态,系统会将所有选中的对象的激活状态同步改变,并标记场景为脏数据(MarkAllScenesDirty),以确保更改会被保存。

在这里插入图片描述

2、绘制Static静态标记


如果当前对象是静态的,则在其旁边绘制一个 “S” 标记,以表示该对象被标记为静态

/// <summary>
/// 绘制静态标记
/// </summary>
private static void DrawStatic(GameObject go, Rect selectionRect, ref int index)
{if (go.isStatic){index++;Rect rect = GetRect(selectionRect, index);GUI.Label(rect, "S");}
}

使用 GUI.Label 方法在计算出的位置上绘制 “S” 标记,以标识静态对象。

在这里插入图片描述

3、绘制组件的Icon


如果对象具有特定的组件(例如 BoxCollider),则在该对象的 Hierarchy 列表项旁边绘制一个图标。

/// <summary>
/// 绘制组件的Icon
/// </summary>
private static void DrawRectIcon<T>(GameObject go, Rect selectionRect, ref int index) where T : Component
{if (go.GetComponent<T>() != null){index++;Rect rect = GetRect(selectionRect, index);DrawIcon<T>(rect);}
}/// <summary>
/// 绘制Unity原生Icon
/// </summary>
private static void DrawIcon<T>(Rect rect)
{var icon = EditorGUIUtility.ObjectContent(null, typeof(T)).image;GUI.Label(rect, icon);
}

该方法检查当前对象是否具有 BoxCollider 组件。

如果对象包含该组件,调用 DrawIcon 方法在计算好的矩形区域中绘制组件的图标。

在这里插入图片描述

4、重绘对象名称


根据对象的激活状态,以不同的颜色在 Hierarchy 窗口中显示对象的名称。

/// <summary>
/// 绘制对象名称
/// </summary>
private static void DrawGameObjectName(GameObject go, Rect selectionRect, GUIStyle activeStyle, GUIStyle inactiveStyle)
{selectionRect.x += 18;GUIStyle style = go.activeSelf ? activeStyle : inactiveStyle;if (PrefabUtility.IsPartOfAnyPrefab(go)) return;GUI.Label(selectionRect, go.name, style);
}

activeStyle 和 inActiveStyle 是用于绘制对象名称的 GUIStyle,分别用于激活状态和非激活状态的对象。

PrefabUtility.IsPartOfAnyPrefab(go) 检查对象是否属于某个预制体(Prefab)。如果对象是预制体的一部分,不执行此绘制,以避免重复显示预制体的名称。

在这里插入图片描述





TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步


END
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

http://www.ppmy.cn/devtools/103692.html

相关文章

win7一键修复所有dll缺失!全面介绍电脑DLL文件丢失修复过程!

在Windows 7操作系统中&#xff0c;DLL&#xff08;动态链接库&#xff09;文件扮演着至关重要的角色。它们是Windows系统和其他应用程序正常运行所必需的组件。然而&#xff0c;由于各种原因&#xff0c;如系统更新不当、软件卸载不完全或恶意软件攻击&#xff0c;DLL文件可能…

EmguCV学习笔记 VB.Net 8.4 pyrMeanShiftFiltering

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

C++ 中的信号量:一种高效的线程同步机制

C 中的信号量&#xff1a;一种高效的线程同步机制 在多线程编程中&#xff0c;线程同步是确保线程安全和避免数据竞争的关键。C 提供了多种线程同步机制&#xff0c;包括互斥锁、条件变量和信号量。今天&#xff0c;我们将深入探讨 C 中的信号量&#xff0c;了解其定义、使用方…

2.2 语言处理程序基础

以编译方式翻译C/C源程序的过程中&#xff0c;类型检查在&#xff08; &#xff09;阶段处理。 A. 词法分析 B. 语义分析 C. 语法分析 D. 目标代码生成 正确答案是 B。 解析 本题考查的是编译器工作过程。 A选项词法分析阶段处理的错误&#xff1a;非法字符、单词拼写错误等。与…

ThinkPHP之入门讲解

文章目录 1 ThinkPHP1.1 框架1.1.1 目录讲解1.1.1.1 5.x1.1.1.2 6.0以上 1.1.2 配置文件1.1.2.1 5.x1.1.2.2 6.0以上 1.1.3 函数文件1.1.3.1 5.x1.1.3.1 6.0以上 1.2 控制器1.2.1 控制器的后缀1.2.2 框架中的命名空间1.2.3 url访问1.2.4 调试模式1.2.4.1 5.x1.2.4.2 6.0以上 1.…

SpringBoot+Vue餐馆点菜系统小程序

项目描述 餐馆点菜系统小程序是一个集成了多种功能的移动应用&#xff0c;旨在提供用户便捷的点餐体验和餐厅高效的订单管理。以下是针对您所提到的功能的简单介绍&#xff1a; 前台小程序&#xff1a;用户通过手机上的小程序&#xff0c;可以浏览餐厅的菜单、选择菜品、下单并…

云端集中管控边缘服务:利用 EMQX ECP 在 K8s 上快速部署 NeuronEX

随着物联网、边缘计算技术的发展&#xff0c;实现边缘服务的快速部署对于分布式计算环境至关重要。它不仅可以显著降低延迟、节省带宽资源、增强数据的安全性和隐私保护&#xff0c;同时还能改善用户体验&#xff0c;支持动态变化的工作负载需求&#xff0c;提供更高的灵活性和…

智能化升级:AI与大数据在TMS中的应用

智能化升级&#xff1a;AI与大数据在TMS中的应用 随着信息技术的飞速发展&#xff0c;AI&#xff08;人工智能&#xff09;与大数据已成为推动各行各业转型升级的重要力量。在物流运输管理领域&#xff0c;TMS&#xff08;运输管理系统&#xff09;作为核心系统&#xff0c;通…

密钥分发与公钥认证:保障网络通信的安全

在网络通信中&#xff0c;密钥的安全分发和公钥的有效认证是确保系统安全的关键。本文将为基础小白介绍密钥分发与公钥认证的基本概念和实际应用&#xff0c;帮助大家更好地理解这些技术如何保障我们的网络通信安全。 1. 密钥分发与公钥认证的背景 由于密码算法是公开的&…

深度学习基础--损失函数

前三章分别介绍了线性回归、浅层神经网络和深度神经网络。这些都属于函数家族&#xff0c;能够实现从输入到输出的映射&#xff0c;其具体的函数取决于模型参数 ϕ \phi ϕ。在训练这些模型时&#xff0c;我们的目标是找到能够为特定任务提供最优输入输出映射的参数。本章将详…

mysql创建只读账户且只能看到部分表

1.首先创建账户 CREATE USER admin% IDENTIFIED BY password1234566...; 解释 CREATE USER admin%: admin: 新用户的用户名是 admin。%: 允许用户 admin 从任何主机连接到 MySQL 服务器。% 是一个通配符&#xff0c;表示没有限制的主机访问。 IDENTIFIED BY password1234566..…

6 自研rgbd相机基于rk3566之深度计算库程序详解

自研rgbd相机基于rk3566之深度计算库详解 1 tof深度计算库框架读入深度图像参数配置tof模组标定参数读入及解析深度计算函数接口2 tof深度计算库程序详解深度计算程序头文件深度计算程序 源文件1 tof深度计算库框架 读入深度图像参数配置 支持raw8/raw10/raw16 格式 /*******…

Ubuntu安装android studio(压缩包版)

#这里适用于linux版压缩版# 1、官网下载Linux版本压缩包 2、下载的文件 .gz,将这个包双击解压出来 3、直接进入解压包的bin目录下&#xff0c;右击在终端打开 3.1、输入 ./studio.sh ./studio.sh 如图所示&#xff1a; 后续操作见图片 下载的时候&#xff0c;直接cancel&…

【面试经验】华为数据产品经理岗位面经

#产品面经# 华为数据产品经理岗位面试的专业笔面试问题&#xff0c;而且我还做了下解析&#xff0c;欢迎大家来讨论&#xff1a; 请阐述数据产品经理在项目中的主要职责和关键任务。解析&#xff1a;考察对岗位的理解深度。如何确保数据的准确性和完整性在产品中的体现&#x…

密码学(二)---DES、SM、RSA

在使用本博客提供的学习笔记及相关内容时&#xff0c;请注意以下免责声明&#xff1a;信息准确性&#xff1a;本博客的内容是基于作者的个人理解和经验&#xff0c;尽力确保信息的准确性和时效性&#xff0c;但不保证所有信息都完全正确或最新。非专业建议&#xff1a;博客中的…

RISC-V单片机智能落地扇方案

在众多产品中&#xff0c;智能落地扇产品凭借其出色的性能和质量优势&#xff0c;备受消费者青睐。智能落地扇有着卓越的性能和智能化的操作。 RAMSUN提供的智能落地扇方案主控单片机芯片采用RISC-V微处理器&#xff0c;内置高速存储器&#xff0c;最高工作频率可达144MHz&…

AI学习记录 - 线性代数(3Blue1Brown)

一天更新一点点&#xff0c;只更新重点内容&#xff0c;一句话定义&#xff0c;简单的定义&#xff0c;避免脑子及记太多 向量的加法就是一种趋势运动 向量的延长缩短&#xff0c;就是分量的延长缩短 基向量就是在平面或者任意维度空间随便定义的一个向量 多个基向量的组合可…

【秋招笔试】8.21华为秋招-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…

800道软件测试面试题与答案+pdf+在线版

2024年软件测试行情不行&#xff0c;今年很多人想着金九银十换一个好工作&#xff0c;几次面试总感觉很多东西明明记住了&#xff0c;突然又忘了。 在整理资料的时候&#xff0c;被我发现一个宝藏内容&#xff01;&#xff01;⚠ 如何准备好面试&#xff0c;大家都头疼我总结…

去中心化(Decentralization)

去中心化&#xff08;Decentralization) 并不是一个新概念&#xff0c;它已在战略、管理和政府中使用了很长时间。去中心化的基本思想是将控制权和权限分配给组织的外围&#xff0c;而不是由一个中心机构完全控制组织。这种配置为组织带来了许多好处&#xff0c;例如提高了效率…