using UnityEngine; using UnityEditor; using UnityEngine.UI; using System.Collections.Generic; using System.IO; using System.Linq; public class FindSelectedPrefabImages : EditorWindow { private string targetFolder = "D:/FB/XiuXianGame/美术/art_use_ui/all"; // 指定外部图片目录(可修改) private Vector2 scrollPosition; [MenuItem("Tools/查找选中预制件中的Sprite图片名称")] public static void ShowWindow() { // 显示编辑器窗口 GetWindow("查找Sprite图片名称"); } void OnGUI() { GUILayout.Label("查找选中预制件中的Sprite图片名称(包括隐藏和所有深层子节点)并删除不匹配的图片", EditorStyles.boldLabel); // 输入外部目标文件夹路径 GUILayout.Label("外部图片文件夹路径(例如 D:/Images):"); targetFolder = EditorGUILayout.TextField(targetFolder); if (GUILayout.Button("查找Sprite图片名称并删除不匹配图片")) { DeleteNonMatchingImages(); } if (GUILayout.Button("开始替换")) { ReplaceImagesInPrefabs(targetFolder); } } private void ReplaceImagesInPrefabs(string path) { string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { path }); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath); if (prefab == null) continue; GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab); bool changed = false; MyImage[] images = instance.GetComponentsInChildren(true); foreach (var img in images) { img.UseGradient = false; changed = true; } if (changed) { PrefabUtility.SaveAsPrefabAsset(instance, assetPath); Debug.Log($"更新了预制件:{assetPath}"); } DestroyImmediate(instance); } AssetDatabase.Refresh(); Debug.Log("替换完成!"); } private void GetName(GameObject obj, HashSet spriteFileNames) { // 查找该对象及其所有子对象(包括深层子节点)的Image组件,包括非活跃的 MyImage img = obj.GetComponent(); if (img != null) { // 获取Sprite的资源路径 // string spritePath = AssetDatabase.GetAssetPath(img.sprite); if (!string.IsNullOrEmpty(img.icon_name) && img.icon_name != "") { spriteFileNames.Add(img.icon_name); } } List images = obj.GetComponentsInChildren(true)?.ToList(); if (images != null && images.Count > 0) { images.Remove(obj.transform); foreach (var myImage in images) { // if (myImage.sprite != null) { GetName(myImage.gameObject, spriteFileNames); } } } } private void DeleteNonMatchingImages() { // 获取当前选中的对象 GameObject[] selectedObjects = Selection.gameObjects; if (selectedObjects.Length == 0) { Debug.LogWarning("没有选中任何对象!"); return; } // 存储Sprite图片的文件名(不含扩展名,忽略大小写) HashSet spriteFileNames = new HashSet(System.StringComparer.OrdinalIgnoreCase); // 查找所有引用的Sprite foreach (GameObject obj in selectedObjects) { // 检查是否为预制件 if (PrefabUtility.IsPartOfAnyPrefab(obj)) { GetName(obj, spriteFileNames); // 查找该对象及其所有子对象(包括深层子节点)的Image组件,包括非活跃的 // MyImage[] images = obj.GetComponentsInChildren(true); // foreach (MyImage img in images) // { // if (img.sprite != null) // { // // 获取Sprite的资源路径 // string spritePath = AssetDatabase.GetAssetPath(img.sprite); // if (!string.IsNullOrEmpty(spritePath)) // { // // 提取文件名(不含扩展名) // string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(spritePath); // spriteFileNames.Add(fileNameWithoutExtension); // // 记录GameObject的层级路径、深度和活跃状态 // string hierarchyPath = GetGameObjectPath(img.gameObject); // int depth = GetHierarchyDepth(img.gameObject); // bool isActive = img.gameObject.activeInHierarchy; // Debug.Log($"找到Sprite: {img.gameObject.name}, 文件名: {fileNameWithoutExtension}, 路径: {spritePath}, 层级: {hierarchyPath}, 层级深度: {depth}, 活跃状态: {(isActive ? "显示" : "隐藏")}"); // } // } // } } } if (spriteFileNames.Count == 0) { Debug.LogWarning("选中的预制件中没有找到任何Sprite图片。"); return; } // 输出所有找到的Sprite文件名 Debug.Log($"找到的Sprite图片文件名: {string.Join(", ", spriteFileNames)}"); // 检查外部目标文件夹是否存在 if (!Directory.Exists(targetFolder)) { Debug.LogError($"外部目标文件夹 {targetFolder} 不存在!"); return; } // 获取目标文件夹中的所有图片文件 string[] imageExtensions = { "*.png", "*.jpg", "*.jpeg", "*.tga" }; List allImageFiles = new List(); foreach (string ext in imageExtensions) { allImageFiles.AddRange(Directory.GetFiles(targetFolder, ext, SearchOption.AllDirectories) .Select(path => path.Replace("\\", "/"))); // 统一路径分隔符 } // 找出需要删除的图片(文件名不匹配Sprite文件名) List filesToDelete = allImageFiles .Where(file => { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); return !spriteFileNames.Contains(fileNameWithoutExtension); }) .ToList(); if (filesToDelete.Count == 0) { Debug.Log("外部目录中没有需要删除的图片文件(所有图片文件名均匹配Sprite文件名)。"); return; } // 确认删除 if (EditorUtility.DisplayDialog("确认删除", $"将要删除 {filesToDelete.Count} 个文件名不匹配Sprite图片的图片文件,是否继续?", "确定", "取消")) { int deletedCount = 0; foreach (string file in filesToDelete) { try { File.Delete(file); Debug.Log($"已删除图片: {file}"); deletedCount++; } catch (System.Exception e) { Debug.LogError($"删除图片失败: {file}, 错误: {e.Message}"); } } Debug.Log($"删除完成,共删除 {deletedCount} 个图片文件。"); } else { Debug.Log("取消删除操作。"); } } // 获取GameObject的层级路径(用于显示递归层级) private string GetGameObjectPath(GameObject obj) { string path = obj.name; while (obj.transform.parent != null) { obj = obj.transform.parent.gameObject; path = obj.name + "/" + path; } return path; } // 计算GameObject的层级深度(根节点为0) private int GetHierarchyDepth(GameObject obj) { int depth = 0; while (obj.transform.parent != null) { obj = obj.transform.parent.gameObject; depth++; } return depth; } }