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

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

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

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

助力快速掌握 Hierarchy 面板扩展

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


文章目录

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


一、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



二、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 事件,当层级结构发生变化时,代码会自动检查是否有同一父对象下的子对象名称重复,并按照从上到下的顺序进行重命名。

在这里插入图片描述



三、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.rhkb.cn/news/412602.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript学习文档(11):Window对象、本地存储、数组中一些方法、学生就业统计表案例

目录 一、Window对象 1、BOM(浏览器对象模型) 2、定时器-延时函数 3、 JS执行机制 &#xff08;1&#xff09;同步任务&#xff1a; &#xff08;2&#xff09;异步任务&#xff1a; 4、location对象 &#xff08;1&#xff09;5秒钟后跳转页面 5、navigator对象 6、…

乐城堡 JoyCastle Unity岗位笔试题

1)实现 move(GameObjct gameObject, Vector3 begin, Vector3 end, float time, bool pingpong){ } 使 gameObject 在 time 秒内&#xff0c;从 begin 移动到 end&#xff0c;若 pingpong 为 true&#xff0c;则在结束时 使 gameObject 在 time 秒内从 end 移动到 begin&#xf…

FPGA上板项目(三)——RAM测试

目录 实验内容实验原理实验步骤实验用时序波形HDL 代码仿真综合实现上板测试 实验内容 对 FPGA 内部的 RAM 进行数据读写操作。 实验原理 RAM &#xff08;Random Access Memory&#xff09;&#xff0c;是可以进行数据交换的存储器&#xff0c;可读可写&#xff1b;而 ROM&…

操作系统:实验六文件操作实验

一、实验目的 1、了解文件系统功能及实现原理。 2、掌握LINUX下文件操作的有关系统调用。 3、熟悉main函数带参数运行的有关操作过程。 4、通过模拟程序实现简单的一级文件系统或二级文件系统。 二、实验内容 1、编程显示文件自身。&#xff08;1分&#xff09; #includ…

Java学习第五天

数组 数组适合做一批同类型数据的存储。 静态初始化数组&#xff1a; 注意&#xff1a;数组变量名中存储的是数组在内存中的地址&#xff0c;数组是引用类型。 数组的访问 动态初始化数组&#xff1a; 数组的遍历&#xff1a; 注意左边和右边的区别&#xff0c;一个是改变数组…

桥接与NET

仔细看看下面两幅图 net模式&#xff0c;就是在你的Windows电脑&#xff08;假设叫A电脑&#xff09;的网络基础上&#xff0c;再生成一个子网络&#xff0c;ip的前两位默认就是192.168&#xff0c;然后第三位是随机&#xff0c;第四位是自己可以手动设置的。使用这种模式唯一的…

grpc-spring 通信(选型,grpc-ecosystem/grpc-spring)

需求 需要一个在稳定网络环境里高性能且开发和部署成本较小&#xff0c;且多平台&#xff0c;且对视频传输和消息订阅和推送的支持比较好的&#xff0c; 一套环境 先说结论因为结论先得到的&#xff0c; 问AI了&#xff0c; 发现一个新东西gRPC ,看了下非常好。 再说过程&…

【2024 CCF编程能力等级认证(GESP)C++ 】一级大纲

目录 1. 背景2. 考核知识块3. 考核内容3.1 计算机基础知识3.2 集成开发环境3.3 结构化程序设计3.4 程序的基本语句3.5 程序的基本概念3.6 基本运算3.7 基本数据类型4. 考核目标5. 题型分布6. 考试时长7. 认证时间与报名8. 政策与福利9. GESP一级认证形式 1. 背景 官网&#xff…

OceanBase V4 技术解读:从Alter Table 看DDL的支持

背景 数据库类型可以划分为两大类&#xff1a;关系型数据库和非关系型数据库。而关系型数据库以表格形式进行数据组织&#xff0c;同时遵循表关系的约束&#xff0c;例如创建一张表&#xff0c;表里面包含多个列&#xff0c;不同的列可以有不同的类型。当需要改表结构&#xf…

数学建模赛前备赛——模拟退火算法

一.什么是智能优化算法 智能优化算法本质上是一个优化算法,它通过不断优化模型的参数,使得系统表现达到最优&#xff0c;常见的只能优化算法有很多&#xff0c;比如说蚁群算法,遗传算法以及我们今天的主角——模拟退火算法。 二.模拟算法的前身——爬山算法 爬山算法是一种简…

开放大世界的碰撞与物理

众所周知&#xff0c;物理开销一直是 CPU 的一个大头&#xff0c;而且还很容易出问题。对于开放世界&#xff0c;该如何进行物理运算&#xff0c;以及采用什么方案计算碰撞。 本文针对这个问题做了一些细微的研究&#xff0c;算是对 Unity 下的解决方案有了一个大致的方向。 1、…

Gartner报告解读:如何帮助企业完善数据分析与治理路线图

Gartner服务于全球100多个国家和地区的14,000余家机构&#xff0c;是一家深受客户信赖、观点客观的研究顾问公司。Garnter洞察、建议和工具可帮助您发现创新机遇&#xff0c;完成关键优先任务&#xff0c;助您成为企业不可或缺的战略专家和价值创造者。该公司是标普 500 指数成…

手把手教在Linux系统服务器下运行HM编码

先在SVN上下载HM文件包&#xff0c;可以看到文件中有linux文件夹&#xff0c;如果在windows下运行直接打开sln后缀的项目。不清楚的看这个&#xff1a; 一、准备工作 1、删除linux文件加下makefile.base中-Werror&#xff0c;文件路径如下&#xff1a; 打开文件&#xff0c;c…

自制深度学习推理框架之表达式层的设计与实现

文章目录 一、表达式Expression二、词法解析2.1 词法定义2.2 词法解析 三、语法解析3.1 语法树的定义3.2 语法树构建3.3 语法树的转换(逆波兰式) 四、表达式层4.1 ExpressionLayer和ExpressionParser类4.2 表达式层的注册4.3 表达式层的输入处理4.4 表达式层的计算过程 五、计算…

插入排序的动画展示与实现

排序学习思路&#xff1a;先实现单趟逻辑&#xff0c;在实现整体逻辑&#xff1b;先解决普遍情况&#xff0c;再解决特殊情况。 什么是插入排序 回忆下自己玩扑克牌的时候是怎么把手上的牌理顺的吧&#xff01;其实那就是插入排序&#xff0c;从左边往右边&#xff0c;把一张张…

Profinet 从站转 EtherNet/IP 从站网关

产品用途 本产品是 PN(Profinet) 和 EtherNet/IP 网关&#xff0c;使用数据映射方式工作。 本产品在 PN 侧作为 PN IO 从站&#xff0c;接 PN 主站设备&#xff0c;比如西门子 PLC 等&#xff1b;在EtherNet/IP 侧做为 EtherNet/IP 从站&#xff0c;接 EtherNet…

C++:继承用法详解~

在学完C的类和对象&#xff0c;并掌握了类的核心语法与基本用法之后&#xff1b;我们就得去学习一下继承的语法&#xff0c;与继承的用法。简单概括一下&#xff0c;继承是C中一种代码复用的手段&#xff0c;它允许我们&#xff0c;对已有的类&#xff0c;增添新的成员函数或变…

opencv实战项目十六:kmeans图像颜色聚类:

文章目录 前言K-means介绍效果 前言 在数字化时代&#xff0c;图像处理技术已成为计算机视觉领域的重要组成部分。其中&#xff0c;图像颜色聚类作为一项关键技术在众多应用场景中发挥着重要作用&#xff0c;如图像分割、物体识别、色彩调整等。K-means算法作为一种经典的聚类…

【云游戏】点量云流赋能大型游戏新体验

点量小刘发现近期国产化大型3A游戏《黑神话&#xff1a;悟空》的发售&#xff0c;可谓是赢得了一波好评。从场景内容来说深厚的文化底蕴支撑和高质量精美的特效及画面制作令人眼前一亮&#xff0c;作为备受瞩目的一款游戏&#xff0c;从技术层面来说&#xff0c;该游戏也离不开…

【DSP+FPGA】基于DSP+FPGA XC7K325T与TMS320C6678的通用信号处理平台

DSP FPGA 协同处理架构板载 1 个TMS320C6678 多核DSP处理节点板载 1 片 XC7K325T FPGA处理节点板载 1 个FMC 接口板载4路SFP光纤接口FPGA 与 DSP 之间采用高速Rapid IO互联 基于FPGA与DSP协同处理架构的通用高性能实时信号处理平台&#xff0c;该平台采用1片TI的KeyStone系列多…