Unity 使用Editor工具查找 Prefab 中的指定脚本
在 Unity 项目中,随着项目规模的扩大和 Prefab 数量的增加,管理和定位 Prefab 中的脚本变得更加复杂。为了提高开发效率,所以需要编写一个自定义的 Unity Editor 工具,帮助查找某个 Prefab 中是否使用了指定的脚本。本文将介绍如何通过 Unity Editor API 来实现一个 "Prefab Script Finder" 工具,该工具可以在 Prefab 模式下帮助查找附带特定脚本的对象,并直接在编辑器中进行选择和高亮。
一、工具实现目标
在本次实现中,我们的目标是构建一个简单且实用的 Unity Editor 工具,通过以下几个步骤实现:
- 允许用户从编辑器中选择某个
MonoScript
,即一个脚本文件。 - 查找当前正在编辑的 Prefab 中是否有 GameObject 附带这个脚本。
- 将找到的对象列出来,并允许开发者在结果列表中点击对象以高亮和定位到该对象。
这个工具非常适合于 Prefab 数量庞大、对象和脚本复杂度较高的项目,有助于快速定位特定组件,提高开发效率。
二、效果

三、代码实现
首先,可以使用 Unity 的 EditorWindow
创建一个自定义的编辑器窗口。在该窗口中,用户可以选择一个脚本文件并点击按钮来查找 Prefab 中附带该脚本的对象。接下来,我们通过递归的方式遍历 Prefab 的所有子对象,检查是否附带指定的脚本。如果找到了,便将这些对象显示在结果列表中。以下是完整的代码实现:
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using UnityEditor.SceneManagement;public class PrefabScriptFinder : EditorWindow
{private MonoScript selectedScript;private string scriptTypeName = "";private List<(GameObject obj, string prefabPath)> foundObjects = new List<(GameObject, string)>();private Vector2 scrollPos;[MenuItem("GameObject/ZYT ASSETS/Prefab Script Finder", false, 100)]public static void ShowWindow(){GetWindow<PrefabScriptFinder>("Prefab Script Finder");}private void OnGUI(){selectedScript = (MonoScript)EditorGUILayout.ObjectField("Script Type", selectedScript, typeof(MonoScript), false);if (selectedScript != null){if (selectedScript.GetClass() != null){scriptTypeName = selectedScript.GetClass().FullName;}else{scriptTypeName = "";}}else{scriptTypeName = "";}if (GUILayout.Button("Find in Prefab")){if (string.IsNullOrEmpty(scriptTypeName)){EditorUtility.DisplayDialog("No Script Selected", "Please select a valid script type.", "OK");return;}FindInPrefab();}if (foundObjects.Count > 0){GUILayout.Space(10);GUILayout.Label("Found Objects:", EditorStyles.boldLabel);scrollPos = GUILayout.BeginScrollView(scrollPos);EditorGUILayout.BeginVertical();// 显示找到的对象列表foreach (var (obj, prefabPath) in foundObjects){// 对象点击可以选中EditorGUI.BeginChangeCheck();GameObject selectedObj = (GameObject)EditorGUILayout.ObjectField(obj, typeof(GameObject), true);if (EditorGUI.EndChangeCheck()){SelectObjectInOpenedPrefab(obj, prefabPath);}}EditorGUILayout.EndVertical();GUILayout.EndScrollView();}}// 在Prefab中查找private void FindInPrefab(){foundObjects.Clear();// 获取当前打开的Prefab场景PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();if (prefabStage == null){EditorUtility.DisplayDialog("No Opened Prefab", "Please open a prefab in Prefab Mode.", "OK");return;}GameObject prefabInstance = prefabStage.prefabContentsRoot;if (prefabInstance == null){EditorUtility.DisplayDialog("Error", "Failed to get the prefab contents.", "OK");return;}// 遍历Prefab中的对象FindObjectsWithScript(prefabInstance.transform, prefabStage.assetPath);if (foundObjects.Count > 0){Repaint();}else{EditorUtility.DisplayDialog("No Results", $"No objects with script '{scriptTypeName}' found in the opened prefab.", "OK");}}// 递归查找带有指定脚本的对象private void FindObjectsWithScript(Transform parent, string prefabPath){foreach (Transform child in parent){Component[] components = child.GetComponents<Component>();foreach (Component comp in components){if (comp != null && comp.GetType().FullName == scriptTypeName){// 将找到的对象和Prefab路径保存foundObjects.Add((child.gameObject, prefabPath));break;}}// 递归检查子对象FindObjectsWithScript(child, prefabPath);}}// 选中Prefab中的对象private void SelectObjectInOpenedPrefab(GameObject obj, string prefabPath){PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();if (prefabStage == null){prefabStage = PrefabStageUtility.OpenPrefab(prefabPath);}if (prefabStage != null){// 选中并高亮对象Selection.activeGameObject = obj;EditorGUIUtility.PingObject(obj);}else{Debug.LogError("Failed to open Prefab in Prefab Mode.");}}
}
四、主要功能解读
-
脚本选择: 用户通过
EditorGUILayout.ObjectField
来选择一个脚本(MonoScript
),当脚本被选择后,我们使用GetClass()
方法来获取该脚本所对应的 C# 类类型,并获取其全名。 -
Prefab 搜索: 我们使用
PrefabStageUtility.GetCurrentPrefabStage()
获取当前正在编辑的 Prefab 场景。如果 Prefab 场景未打开,我们提示用户打开 Prefab 模式。然后我们通过递归遍历 Prefab 中的每一个子对象,检查对象上是否附带了指定的脚本。 -
结果显示: 找到的对象会被列出,并且用户可以点击每一个对象,工具将自动高亮并选中该对象,方便用户进行进一步操作。
-
递归查找: 通过递归遍历 Prefab 的子节点,确保我们不会遗漏任何对象。每一个带有指定脚本的对象都会被保存到结果列表中。
五、工具的优势
- 快速查找: 在复杂的项目中,Prefab 中的对象可能非常多,手动查找是低效的。这个工具能快速帮助开发者找到指定脚本。
- 结果交互: 找到的对象直接在编辑器中展示,点击即可选中,并进行定位,非常方便。
六、总结
本文介绍的 "Prefab Script Finder" 是一个实用的 Unity Editor 工具,能够帮助开发者快速在 Prefab 中查找附带特定脚本的对象。通过这种方式,我们可以减少开发过程中的重复劳动,快速定位问题所在,并提高整体开发效率。
相关文章:

Unity 使用Editor工具查找 Prefab 中的指定脚本
在 Unity 项目中,随着项目规模的扩大和 Prefab 数量的增加,管理和定位 Prefab 中的脚本变得更加复杂。为了提高开发效率,所以需要编写一个自定义的 Unity Editor 工具,帮助查找某个 Prefab 中是否使用了指定的脚本。本文将介绍如何…...
Frida-JSAPI:Interceptor使用
拦截器 Interceptor.attach(target, callbacks[, data]) 参数分析 target :target是一个NativePointer,用于指定想要拦截的函数的地址。callbacks :参数是一个包含一个或多个回调函数的对象。 onEnter(args) 回调函数,接收一个参…...

【深度学习】(3)--损失函数
文章目录 损失函数一、L1Loss损失函数1. 定义2. 优缺点3. 应用 二、NLLLoss损失函数1. 定义与原理2. 优点与注意3. 应用 三、MSELoss损失函数1. 定义与原理2. 优点与注意3. 应用 四、BCELoss损失函数1. 定义与原理2. 优点与注意3. 应用 五、CrossEntropyLoss损失函数1. 定义与原…...

git学习报告
文章目录 git学习报告如何配置vscode终端安装PowerShell安装 Microsoft.Powershell.Preview使用 git的使用关于团队合作 git指令本地命令:云端指令 git学习报告 如何配置vscode 安装powershell调教window终端,使其像Linux一样,通过Linux命令…...

Spring MVC的应用
目录 1、创建项目与maven坐标配置 2、核心配置 3、启动项目测试 4、不同请求参数在controller的配置 4.1 servlet API 4.2 简单类型 4.3 pojo类型 4.4 日期类型 4.5 restful风格4种操作类型 4.5.1 GET:获取资源 4.5.2 POST:新建资源 4.5.3 P…...

JavaEE: 深入探索TCP网络编程的奇妙世界(六)
文章目录 TCP核心机制TCP核心机制九: 面向字节流TCP核心机制十: 异常处理 小小的补充(URG 和 PSH)~TCP小结TCP/UDP 对比用UDP实现可靠传输(经典面试题) 结尾 TCP核心机制 上一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(五) 书接上文~ TCP核心机制九: 面向字节流 TCP是面…...

探秘 Web Bluetooth API:连接蓝牙设备的新利器
引言 随着物联网技术的快速发展,蓝牙设备在日常生活中扮演着越来越重要的角色。而在 Web 开发领域,Web Bluetooth API 的出现为我们提供了一种全新的方式来连接和控制蓝牙设备。本文将深入探讨 Web Bluetooth API 的使用方法和原理,帮助开发…...

Kubernetes Pod调度基础(kubernetes)
实验环境依旧是k8s快照,拉取本次实验所需的镜像文件; 然后在master节点上传已经编写好的yaml文件; 然后同步会话,导入镜像; pod控制器: 标签选择器--》标签: 标签: 在Kubernetes&…...

Angular由一个bug说起之十:npm Unsupported engine
我们在用npm下载包的时候,有时候会碰到这样的提示 这是npm的警告,说我们使用的nodejs版本与下载的包所要求的nodejs版本不一致。 这是因为有些包它对nodejs的版本有要求,然后就会在package.json文件里的engines字段里声明它所要求的nodejs版本…...

Android 开发高频面试题之——Flutter
Android开发高频面试题之——Java基础篇 flutter高频面试题记录 Flutter1. dart中的作用域与了解吗2. dart中. .. ...分别是什么意思?3. Dart 是不是单线程模型?如何运行的?4. Dart既然是单线程模型支持多线程吗?5. Future是什么6. Stream是什么7. Flutter 如何和原生交互…...

视频单目标跟踪研究
由于对视频单目标跟踪并不是很熟悉,所以首先得对该领域有个大致的了解。 视频目标跟踪是计算机视觉领域重要的基础性研究问题之一,是指在视频序列第一帧指定目标 后,在后续帧持续跟踪目标,即利用边界框(通常用矩形框表…...

若依vue3.0表格的增删改查文件封装
一、因若依生成的文件没进行封装,维护起来比较麻烦。所以自己简单的进行封装了一下 gitee代码(文件)地址:https://gitee.com/liu_yu_ting09/ruo_yi.git 二、封装的方法(下面绿色按钮进行全局封装一个JeecgListMixin.js…...
【已解决】如何使用JAVA 语言实现二分查找-二分搜索折半查找【算法】手把手学会二分查找【数据结构与算法】
文章目录 前言任务描述编程要求 输出样例:未查找到11元素! 二、代码实现总结理解不了考试的时候直接背下来就好了。 前言 [TOC]二分搜索 任务描述 折半查找(二分搜索) 设a[low..high]是当前的查找区间,首先确定该区间的中点位置…...
ERROR 1524 (HY000): Plugin ‘mysql_native_password‘ is not loaded
你遇到的错误是由于 MySQL 版本不再默认支持 mysql_native_password 认证插件导致的。从 MySQL 8.0 开始,默认的认证插件是 caching_sha2_password,而不是 mysql_native_password。 解释: 错误 ERROR 1524 (HY000): Plugin mysql_native_pa…...

.NET 6.0 WebAPI 使用JWT生成Token的验证授权
1.引入相关程序包JwtBearer注意版本: 2.配置文件appsettings.json写相关配置参数(也可不写,写在程序里面,数据库读取也是一样的) , //JWT加密"JWTToken": {"SecretKey": "jsaduwqe6asdjewejdue7dfmsdfu0sdfmwmsd8wfsd6",…...

M9410A VXT PXI 矢量收发信机,300/600/1200MHz带宽
M9410A PXI 矢量收发信机 -300/600/1200MHz带宽- M9410A VXT PXI 矢量收发信机,300/600/1200MHz带宽支持 5G 的 PXI 矢量收发信机(VXT)是一个 2 插槽模块,具有 1.2 GHz 的瞬时带宽 主要特点 Keysight M9410A VXT PXIe 矢量收发…...
用工厂模式演示springboot三种注入方式 | @Autowired
背景:看了个demo工厂模式,示例代码的工厂类是new出来的,但是实际项目中都是用springboot框架、bean都是会给容器管理的,所以在思考这个工厂类要交给springboot托管要怎么改。以下是总结笔记 依赖注入 1.工厂类用new实现2.工厂类用…...
es查询语法
查询关键词的含义: match: 用于进行全文搜索,分析查询文本并与倒排索引中的词项进行匹配。 term: 精确匹配,适用于非分析字段,如 keyword 类型。用于查找字段值完全相等的文档。 bool: 组合多个查询条件。可以使用 must…...

LabVIEW提高开发效率技巧----合理使用数据流与内存管理
理使用数据流和内存管理是LabVIEW开发中提高性能和稳定性的关键,特别是在处理大数据或高频率信号时,优化可以避免内存消耗过大、程序卡顿甚至崩溃。 1. 使用 Shift Register 进行内存管理 Shift Register(移位寄存器) 是 LabVIE…...
如何在 ECharts 中设置轴标签
在 ECharts 中,轴标签(Axis Label)是指 X 轴或 Y 轴上的刻度标签,用于显示轴上的数据值或分类名称。你可以通过配置 xAxis(X 轴)或 yAxis(Y 轴)的 axisLabel 属性来设置轴标签的样式…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...