using UnityEngine; using UnityEditor; using System.IO; using System.Collections.Generic; using System.Text; using Thousandto.Editor.Excel; public class CheckInvalidUISpriteEditor : EditorWindow { [MenuItem("Ares/检查无效的UISprite")] static void DoIt() { var win = (CheckInvalidUISpriteEditor)EditorWindow.GetWindow(typeof(CheckInvalidUISpriteEditor)); win.Show(); } private string _prefabPath = string.Empty; private Dictionary> _showTexts = new Dictionary>(65535); void OnGUI() { EditorGUILayout.BeginVertical(); EditorGUILayout.LabelField("选择路径"); EditorGUILayout.Space(); EditorGUILayout.LabelField("需要检测的UIForm路径"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("浏览", GUILayout.Width(100))) { _prefabPath = EditorUtility.OpenFolderPanel("Check UIForm Prefab Path", _prefabPath, ""); } if (string.IsNullOrEmpty(_prefabPath)) { EditorGUILayout.LabelField("null..."); } else { EditorGUILayout.LabelField(_prefabPath); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); if (GUILayout.Button("检测并导出", GUILayout.Width(100))) { string excelPath = EditorUtility.SaveFilePanel("Export Excel", "", "InvalidUISprite", "xlsx"); if (string.IsNullOrEmpty(excelPath)) return; if (string.IsNullOrEmpty(_prefabPath)) return; if (Directory.Exists(_prefabPath)) { _showTexts.Clear(); var rowCount = 0; DirectoryInfo direction = new DirectoryInfo(_prefabPath); FileInfo[] files = direction.GetFiles("*.prefab", SearchOption.AllDirectories); for (int i = 0; i < files.Length; ++i) { var path = files[i].FullName.Replace('\\', '/'); var starIndex = path.IndexOf("/Assets/", 0); path = path.Remove(0, starIndex + 1); var go = AssetDatabase.LoadAssetAtPath(path); if (go != null) { var fileName = files[i].Name; fileName = fileName.Replace(".prefab", ""); var csCodePath = files[i].FullName.Replace('\\', '/'); csCodePath = csCodePath.Remove(starIndex); csCodePath = csCodePath + "/Assets/GameAssets/Resources/GameUI/Form/" + fileName; List codeTexts = new List(64); if(Directory.Exists(csCodePath)) { DirectoryInfo csdirection = new DirectoryInfo(csCodePath); FileInfo[] csFiles = csdirection.GetFiles("*.cs", SearchOption.AllDirectories); for (int j = 0; j < csFiles.Length; ++j) { codeTexts.Add(File.ReadAllText(csFiles[j].FullName)); } } var luaCodePath = files[i].FullName.Replace('\\', '/'); luaCodePath = luaCodePath.Remove(starIndex); luaCodePath = luaCodePath + "/Assets/GameAssets/Resources/Lua/UI/Forms/" + fileName; if(Directory.Exists(luaCodePath)) { DirectoryInfo luadirection = new DirectoryInfo(luaCodePath); FileInfo[] luaFiles = luadirection.GetFiles("*.lua", SearchOption.AllDirectories); for (int j = 0; j < luaFiles.Length; ++j) { codeTexts.Add(File.ReadAllText(luaFiles[j].FullName)); } } var sprites = go.GetComponentsInChildren(true); for (int j = 0; j < sprites.Length; ++j) { if(!IsUsedSprite(sprites[j], codeTexts)) { List findList = null; if (!_showTexts.TryGetValue(fileName, out findList)) { findList = new List(); _showTexts.Add(fileName, findList); ++rowCount; } findList.Add(FindNodePath(sprites[j].gameObject, fileName)); ++rowCount; } } } } NormalExcelInfo excelInfo = new NormalExcelInfo(); excelInfo.Name = "InvalidUISprite"; excelInfo.Values = new string[rowCount, 2]; var iter = _showTexts.GetEnumerator(); int curRow = 0; while(iter.MoveNext()) { excelInfo.Values[curRow++, 0] = iter.Current.Key; for(int i = 0; i < iter.Current.Value.Count;++ i) { excelInfo.Values[curRow++, 1] = iter.Current.Value[i]; } } ExcelWriter.Write(excelPath, excelInfo); _showTexts.Clear(); } } } private bool IsUsedSprite(UISprite sprite, List codeText) { var name = sprite.name; if (name == "Icon" || name == "Bind") return true; if (sprite.GetAtlasSprite() == null || !sprite.gameObject.activeSelf) { string number = string.Empty; bool findNumber = false; for (int i = 0; i < name.Length; ++i) { if (name[i] >= '0' && name[i] <= '9') { number += name[i]; findNumber = true; } else if (findNumber) { break; } } var findText1 = name + "\""; var findText2 = string.Empty; var findText3 = string.Empty; if (!string.IsNullOrEmpty(number)) { findText2 = name.Replace(number, "{0}"); findText3 = name.Replace(number, "%d"); } //需要检测是否代码有调用 bool isFind = false; for (int k = 0; k < codeText.Count; ++k) { if (codeText[k].IndexOf(findText1) >= 0) { isFind = true; break; } if (!string.IsNullOrEmpty(findText2) && codeText[k].IndexOf(findText2) >= 0) { isFind = true; break; } if (!string.IsNullOrEmpty(findText3) && codeText[k].IndexOf(findText3) >= 0) { isFind = true; break; } } return isFind; } return true; } private string FindNodePath(GameObject go, string formName) { StringBuilder pathSB = new StringBuilder(); pathSB.Length = 0; Transform parent = go.transform; while (parent != null && parent.name != formName) { string cpPath = "/" + parent.gameObject.name; pathSB.Insert(0, cpPath); parent = parent.transform.parent; } return pathSB.ToString().TrimStart('/'); } }