Unity Editor 扩展:查找缺失的 Image Sprite

在 Unity 开发过程中,缺失的 Sprite 引用(特别是在 UI 元素上)可能导致程序运行时出现问题,尤其是在使用 Image 组件时。当你拥有多个 Prefab 和大量的 UI 资源时,手动检查每个 Prefab 是否缺失了 Source Image 变得十分繁琐。

为了提高开发效率,今天我们来编写一个 Unity 编辑器脚本,通过查找 Prefab 中是否存在缺失的 Image 组件的 Sprite,帮助你快速定位缺失的资源。

目标

该脚本的主要目标是:

  • 遍历选中的文件夹中的 Prefab 文件。
  • 查找每个 Prefab 内的 Image 组件。
  • 如果 Image 组件的 Sprite 为空,则标记该节点为缺失,并记录其路径。
  • 在编辑器窗口中显示这些缺失的节点,供开发者定位和修复。

脚本解析 

1. 初始化窗口

我们首先通过 EditorWindow 创建一个自定义的 Unity 编辑器窗口。

public class MissingImageSpriteFinder : EditorWindow
{private Vector2 scrollPos;private List<ResultData> resultList = new List<ResultData>();private class ResultData{public GameObject prefab;public List<string> nodePaths = new List<string>();}
}

 这里,我们创建了一个 ResultData 类来存储每个 Prefab 和包含缺失 Sprite 的节点路径。在 MissingImageSpriteFinder 类中,我们定义了一个 resultList 来存储所有找到的结果。

2. 添加菜单项

我们通过 MenuItem 特性将功能添加到 Unity 编辑器的菜单中,方便开发者直接点击执行。

[MenuItem("Assets/Find Missing SourceImage", false, 49)]
public static void FindMissingImages()
{var window = GetWindow<MissingImageSpriteFinder>("Find Missing SourceImage Result");window.Search();
}

 此方法会在 Unity 编辑器中创建一个新的菜单项 查找 Missing 的 SourceImage,点击该菜单项时,会打开 MissingImageSpriteFinder 窗口并开始搜索缺失的 Sprite

3. 搜索逻辑

Search 方法中,我们首先清空结果列表,然后获取选中的文件夹路径,遍历其中的 Prefab 文件。

private void Search()
{resultList.Clear();string[] selectedGuids = Selection.assetGUIDs;foreach (string guid in selectedGuids){string path = AssetDatabase.GUIDToAssetPath(guid);if (!AssetDatabase.IsValidFolder(path)) continue;string[] prefabPaths = Directory.GetFiles(path, "*.prefab", SearchOption.AllDirectories);foreach (string prefabPath in prefabPaths){GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);if (prefab == null) continue;Transform[] children = prefab.GetComponentsInChildren<Transform>(true);List<string> missingNodes = new List<string>();foreach (Transform t in children){Image img = t.GetComponent<Image>();if (img != null && IsMissingReference(img, "m_Sprite")){string nodePath = GetTransformPath(t, prefab.transform);missingNodes.Add(nodePath);}}if (missingNodes.Count > 0){resultList.Add(new ResultData{prefab = prefab,nodePaths = missingNodes});}}}Repaint();
}

在这个方法中,我们做了以下几件事:

  • 获取当前选中的文件夹路径。
  • 查找该文件夹及其子文件夹中的所有 Prefab 文件。
  • 对每个 Prefab 文件进行处理,查找所有子节点中的 Image 组件。
  • 如果 Image 组件的 Sprite 属性为空,则认为是缺失的,并记录该节点的路径。

4. 界面显示

OnGUI 方法中,我们定义了自定义窗口的显示逻辑。

private void OnGUI()
{GUILayout.Label("查找结果", EditorStyles.boldLabel);if (resultList.Count == 0){EditorGUILayout.HelpBox("未找到缺失的 SourceImage。", MessageType.Info);return;}scrollPos = EditorGUILayout.BeginScrollView(scrollPos);foreach (var result in resultList){EditorGUILayout.BeginVertical("box");EditorGUILayout.ObjectField("Prefab", result.prefab, typeof(GameObject), false);EditorGUILayout.LabelField("包含 Missing Sprite 的节点路径:");foreach (var path in result.nodePaths){EditorGUILayout.LabelField(" - " + path);}if (GUILayout.Button("定位 Prefab", GUILayout.Width(100))){Selection.activeObject = result.prefab;EditorGUIUtility.PingObject(result.prefab);}EditorGUILayout.EndVertical();}EditorGUILayout.EndScrollView();
}
  • 首先显示了一个标题标签。
  • 如果没有找到缺失的 Sprite,会显示一条提示消息。
  • 如果有找到缺失的 Sprite,则在滚动视图中列出每个 Prefab 和其包含缺失 Sprite 的节点路径。
  • 每个 Prefab 后面有一个按钮,点击后会自动选中该 Prefab 并在场景中高亮显示。

5. 辅助方法

IsMissingReferenceGetTransformPath 方法分别用于判断 Image 组件的 Sprite 是否为空,并获取节点相对 Prefab 的路径。

private bool IsMissingReference(Object obj, string propertyName)
{SerializedObject so = new SerializedObject(obj);SerializedProperty sp = so.FindProperty(propertyName);return sp != null && sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0;
}private string GetTransformPath(Transform current, Transform root)
{List<string> path = new List<string>();while (current != null && current != root){path.Insert(0, current.name);current = current.parent;}return string.Join("/", path);
}
  • IsMissingReference 通过检查 Image 组件的 m_Sprite 属性是否为空,判断是否为缺失的引用。
  • GetTransformPath 通过遍历节点的父节点,构建从根节点到当前节点的路径。

完整代码

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.Collections.Generic;
using System.IO;public class MissingImageSpriteFinder : EditorWindow
{private Vector2 scrollPos;private List<ResultData> resultList = new List<ResultData>();private class ResultData{public GameObject prefab;public List<string> nodePaths = new List<string>();}[MenuItem("Assets/Find Missing SourceImage", false, 49)]public static void FindMissingImages(){var window = GetWindow<MissingImageSpriteFinder>("Find Missing SourceImage Result");window.Search();}private void Search(){resultList.Clear();string[] selectedGuids = Selection.assetGUIDs;foreach (string guid in selectedGuids){string path = AssetDatabase.GUIDToAssetPath(guid);if (!AssetDatabase.IsValidFolder(path)) continue;string[] prefabPaths = Directory.GetFiles(path, "*.prefab", SearchOption.AllDirectories);foreach (string prefabPath in prefabPaths){GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);if (prefab == null) continue;Transform[] children = prefab.GetComponentsInChildren<Transform>(true);List<string> missingNodes = new List<string>();foreach (Transform t in children){Image img = t.GetComponent<Image>();if (img != null && IsMissingReference(img, "m_Sprite")){string nodePath = GetTransformPath(t, prefab.transform);missingNodes.Add(nodePath);}}if (missingNodes.Count > 0){resultList.Add(new ResultData{prefab = prefab,nodePaths = missingNodes});}}}Repaint();}private void OnGUI(){GUILayout.Label("查找结果", EditorStyles.boldLabel);if (resultList.Count == 0){EditorGUILayout.HelpBox("未找到缺失的 SourceImage。", MessageType.Info);return;}scrollPos = EditorGUILayout.BeginScrollView(scrollPos);foreach (var result in resultList){EditorGUILayout.BeginVertical("box");EditorGUILayout.ObjectField("Prefab", result.prefab, typeof(GameObject), false);EditorGUILayout.LabelField("包含 Missing Sprite 的节点路径:");foreach (var path in result.nodePaths){EditorGUILayout.LabelField(" - " + path);}if (GUILayout.Button("定位 Prefab", GUILayout.Width(100))){Selection.activeObject = result.prefab;EditorGUIUtility.PingObject(result.prefab);}EditorGUILayout.EndVertical();}EditorGUILayout.EndScrollView();}// 判断是否是 Missing 的引用private bool IsMissingReference(Object obj, string propertyName){SerializedObject so = new SerializedObject(obj);SerializedProperty sp = so.FindProperty(propertyName);return sp != null && sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0;}// 获取节点相对 prefab 的路径private string GetTransformPath(Transform current, Transform root){List<string> path = new List<string>();while (current != null && current != root){path.Insert(0, current.name);current = current.parent;}return string.Join("/", path);}
}

效果预览

右键选中文件夹 选择Find Missing SourceImage

效果如下

总结

通过编写这个自定义的 Unity 编辑器扩展,你可以高效地查找和修复缺失的 Image 组件的 Sprite 引用。它能够自动扫描选定的文件夹中的所有 Prefab,并定位其中的缺失引用,大大节省了手动检查的时间。

如果你的项目中包含大量的 UI Prefab 和资源,这个工具将是你提高生产力的重要助手。希望这篇博客对你有所帮助,快去试试吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/79895.shtml

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

相关文章

在VTK中使用VTKCamera

文章目录 概要Cpp代码概要 在VTK(Visualization Toolkit)中,vtkCamera 类用于控制三维场景中相机的视角。相机决定了你从哪个角度和位置观察三维场景。使用 vtkCamera 的一般步骤包括创建相机对象、配置相机参数、将相机设置为渲染器的活动相机,以及更新相机视图。 Cpp代…

【Docker系列】使用格式化输出与排序技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

临床智能体AI与环境感知AI的融合:基于python的医疗自然语言处理深度分析

引言 医疗领域的数智化进程正以前所未有的速度推进,人工智能技术的应用尤为显著。随着大型语言模型(LLMs)的迅猛发展,医疗AI已从简单的辅助工具升级为复杂的智能体系统。临床智能体AI与环境感知AI的融合代表了医疗AI的最新发展方向,为重塑医疗运营自然语言处理提供了全新…

JAVA SE(9)——多态

1.多态的概念&作用 多态(Polymorphism)是面向对象编程的三大基本特性之一&#xff08;封装和继承已经讲过了&#xff09;&#xff0c;它允许不同类的对象对同一消息做出不同的响应。具体来说&#xff0c;多态允许基类/父类的引用指向派生类/子类的对象&#xff08;向上转型…

GPS定位方案

目录 一、常用的GPS定位方案包括&#xff1a; 二、主流品牌及热销型号 三、常用GPS算法及核心逻辑&#xff1a; 一、基础定位算法 二、高精度算法 三、辅助优化算法 四、信号处理底层算法 四、基本原理&#xff08;想自己写算法的琢磨一下原理&#xff09; 一、常用的GP…

PCIe - ZCU106(RC) + KU5P(EP) + 固化

目录 1. 简介 1.1 Data Mover 1.2 描述符 2. ZCU102 2.1 Ubuntu OS 2.2 USB Host 2.2.1 连接拓扑 2.2.2 设备类型 2.2.3 USB 跳帽设置 2.3 无线网卡 2.4 PCIe Info 2.4.1 Diagram 2.4.2 lspci -tv 2.4.3 lspci -v 2.4.2.1 设备基本信息 2.4.2.2 控制与状态寄存…

精益数据分析(43/126):媒体网站商业模式的盈利与指标解析

精益数据分析&#xff08;43/126&#xff09;&#xff1a;媒体网站商业模式的盈利与指标解析 在创业和数据分析的学习旅程中&#xff0c;我们不断探索各种商业模式的奥秘&#xff0c;今天让我们一同深入《精益数据分析》&#xff0c;聚焦媒体网站商业模式&#xff0c;剖析其盈…

Android数据库全栈开发实战:Room+SQLCipher+Hilt企业级应用构建

简介 在移动应用开发中,数据库作为数据存储的核心组件,其安全性和性能对企业级应用至关重要。本文将从零开始,全面讲解Android数据库开发的最新技术,包括Room框架的深度使用、SQLCipher加密数据库的实现、Hilt依赖注入的集成以及前后端数据同步的完整方案。通过一个加密任…

HarmonyOS 5.0 低时延音视频开发​​

大家好&#xff0c;我是 V 哥。 在HarmonyOS 5.0的开发中&#xff0c;支持低时延音视频开发&#xff0c;为了确保语法正确&#xff0c; V 哥以下代码符合HarmonyOS NEXT API 14的规范。为了方便初学者更好入门&#xff0c;V 哥伙同2位小伙伴花了1年时间&#xff0c;搞了三本鸿蒙…

微调大模型如何准备数据集——常用数据集,Alpaca和ShareGPT

微调大模型如何准备数据集——常用数据集,Alpaca和ShareGPT 数据集准备常用数据集自定义数据集AlpacaShareGPT数据集准备 常用数据集 预训练数据集 Wiki Demo (en)RefinedWeb (en)RedPajama V2 (en)Wikipedia (en)Wikipedia (zh)Pile (en)

2025年OpenAI重大架构调整:资本与使命的再平衡

目录 前言 一、调整核心&#xff1a;三重架构的重构 1.1 控制权的重新锚定 1.2 营利部门的角色转型 1.3 资金池的重新配置 二、调整动因&#xff1a;三重矛盾的破解 2.1 资金需求与融资限制的冲突 2.2 商业竞争与使命纯度的博弈 2.3 内部治理与外部监管的张力 三、产…

GD32/STM32 ADC/DMA使用指南

首先我们对ADC及DMA的基础知识作一下简单介绍。 一、 GD32/STM32 ADC模块的核心要点 一&#xff09;、ADC基础特性 ‌12位逐次逼近型‌ GD32/STM32 ADC为12位分辨率&#xff0c;最大量化值为4095&#xff08;对应3.3V参考电压&#xff09;&#xff0c;支持0-3.3V模拟输入范…

Linux(十四)进程间通信(IPC),管道

一、进程间通信 &#xff08;一&#xff09;系统介绍进程间通信 进程间通信&#xff08;IPC&#xff09;介绍 小编插入的这篇文章详细介绍了进程间通信的一些内容&#xff0c;大家可以一起学习。 &#xff08;二&#xff09;进程间通信的方法 1、管道 2、信号量 3、共享…

使用Homebrew下载配置git和连接GitHub(Mac版)

本文详细介绍了在M系列Mac上安装Homebrew并配置Git的过程&#xff0c;包括git的下载、设置全局用户名和邮箱、生成SSH密钥、添加GitHubSSH密钥以及终端验证。这些步骤有助于用户顺利进行协同开发。 一、下载git 1、终端输入一下命令 brew install git2、这时下载完成 二、配…

悬崖边的摄影牧歌

在云雾缭绕的悬崖边&#xff0c;一场独属于自然与光影的邂逅悄然上演。 摄影师伫立于此&#xff0c;身旁是一群灵动的羊。他架起相机&#xff0c;眼神专注而炽热&#xff0c;仿佛要将这天地间的一切都收纳进小小的取景器。悬崖陡峭&#xff0c;岩石冷峻&#xff0c;却因羊群的洁…

Linux环境基础与开发工具使用

1. Linux编译器vim 1.1 vim的基本概念讲解 vim有很多种模式&#xff0c;我们初学者常用的就是命令模式&#xff08;command mode&#xff09;、插入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08;last line mode&#xff09;。 命令/正常模式(Normal mode) …

《Python星球日记》 第36天:线性代数基础

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏&#xff1a;《Python星球日记》&#xff0c;限时特价订阅中ing 目录 一、标量、…

使用VMware Workstation pro 17.5.1在Windows上安装Ubuntu 24.04.2的 详细步骤

一、准备工作 1. 下载Ubuntu 24.04.2 ISO镜像 官方下载地址&#xff1a;Ubuntu 24.04.2 (Noble Numbat) 选择 ubuntu-24.04.2-desktop-amd64.iso&#xff08;桌面版&#xff09;或 ubuntu-24.04.2-live-server-amd64.iso&#xff08;服务器版&#xff09;。 2. 确认系统要求…

ios systeam introduction

Here is an in-depth look at Apple’s iOS, from its inception to its latest major release, covering architecture, core components, security, app lifecycle, development tools, and the headline features of iOS 18. iOS began life as “iPhone OS,” unveiled alo…

优化04-选择率和直方图

选择率 在Oracle数据库中&#xff0c;选择率&#xff08;Selectivity&#xff09; 是优化器&#xff08;CBO&#xff0c;基于成本的优化器&#xff09;用来评估SQL语句中某个条件&#xff08;如WHERE子句&#xff09;过滤数据的比例的关键指标。它直接影响优化器选择执行计划的…