using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using System.Linq; using UnityEditor; using System.Text; using System.Text.RegularExpressions; using GameLogic; /// /// 查找无引用资源(当前为贴图)version 2.0 /// Copyright (c) 2018 Ganchong Xingli /// public class FindNoReferenceAssetWindow:EditorWindow { /// /// 匹配资源类型库 /// public static string ContainsExtensions = "*.prefab*.unity*.mat*.asset"; /// /// Lua文件夹屏蔽库 /// public static string WithoutLuaExtensions = "*3rd*.idea*Base*Common*UITools*Logic*"; /// /// 所有游戏 /// string[] games; /// /// 匹配资源类型库 /// string containsExtensions = ContainsExtensions; /// /// Lua文件夹屏蔽库 /// string withoutLuaExtensions = WithoutLuaExtensions; /// /// 是否检查所有游戏 /// bool isCheckAllGames; /// /// 是否交叉检查 /// bool isCorssCheck; /// /// 是否显示动态加载列表 /// bool isShowDynamicList; /// /// 资源GUID列表 /// List AssetFileGuidList; /// /// 无引用资源 guid列表 /// List NoRefAssetGuidList; /// /// 没有直接引用但动态加载列表 /// Dictionary DynamicLoadAssetList; /// /// 所有检查的游戏 /// Dictionary CheckGames; /// /// 查找资源目录 /// public static string FindPath = AppConst.GameResRealPath + "/{0}"; /// /// 资源目录 /// public static string AssetPath = AppConst.GameResRealPath + "/{0}/Atlas"; /// /// Lua文件路径 /// public static string LuaFilesPath = AppConst.GameResRealPath + "/{0}/~Lua"; List checkList = new List(); [MenuItem("Tools/查找无引用贴图", false, 1)] static void Init() { // Get existing open window or if none, make a new one: FindNoReferenceAssetWindow window = (FindNoReferenceAssetWindow)EditorWindow.GetWindow(typeof(FindNoReferenceAssetWindow)); window.Show(); window.titleContent = new GUIContent("查找无引用资源"); window.InitWindow(); } /// /// 初始化窗口 /// void InitWindow() { InitSize(); InitGames (); //FindNoReferences(); } /// /// 初始化大小 /// void InitSize() { minSize = new Vector2(512, 400); maxSize = new Vector2(512, 400); } /// /// 初始化游戏 /// void InitGames() { CheckGames = new Dictionary (); games = Directory.GetDirectories(AppConst.GameResRealPath); for (int i = 0; i < games.Length; i++) { games[i] = Path.GetFileNameWithoutExtension(games[i]); CheckGames.Add (games[i],false); } } void OnGUI() { ShowCheckGames (); ShowWithout(); ShowButtons(); } /// /// 选择哪些游戏需要检查 /// void ShowCheckGames() { EditorGUILayout.BeginVertical(); EditorGUILayout.HelpBox("请勾选需要检查的游戏", MessageType.None, true); //全选/反选 bool tmpAllGames = isCheckAllGames; isCheckAllGames = EditorGUILayout.Toggle("All/None", isCheckAllGames); EditorGUILayout.Space(); if (tmpAllGames != isCheckAllGames) { string[] keys = CheckGames.Keys.ToArray(); foreach (var each in keys) { CheckGames[each] = isCheckAllGames; } } for (int i = 0; i < games.Length; i++) { CheckGames[games[i]] = EditorGUILayout.Toggle(games[i], CheckGames[games[i]]); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.BeginVertical(); isCorssCheck = EditorGUILayout.Toggle("是否交叉检查?", isCorssCheck); isShowDynamicList = EditorGUILayout.Toggle("是否显示动态加载列表?", isShowDynamicList); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); } /// /// 显示屏蔽库 /// void ShowWithout() { EditorGUILayout.BeginVertical(); containsExtensions = EditorGUILayout.TextField("匹配资源类型库?", containsExtensions); withoutLuaExtensions = EditorGUILayout.TextField("Lua文件夹屏蔽库?", withoutLuaExtensions); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); } /// /// 显示Build按钮 /// void ShowButtons() { if (GUILayout.Button("开始检查", GUILayout.Height(40f))) { FindNoReferences(); } } /// /// 查找无引用贴图 /// void FindNoReferences() { checkList.Clear(); if (isCorssCheck) { ResetList(); foreach (var game in CheckGames) { if (!game.Value) continue; CollectAllAsset(game.Key); } foreach(var game in CheckGames) { if (!game.Value) continue; checkList.Add(game.Key); } ResetList(); CollectAllAsset(checkList[0]); FindReferences(checkList[0]); } else { foreach (var game in CheckGames) { if (!game.Value) continue; checkList.Add(game.Key); } ResetList(); CollectAllAsset(checkList[0]); FindReferences(checkList[0]); } } void ResetList() { AssetFileGuidList = new List(); NoRefAssetGuidList = new List(); DynamicLoadAssetList = new Dictionary(); } /// /// 搜集所有的资源 /// void CollectAllAsset(string game) { string assetPath = string.Format(AssetPath, game); var files = Directory.GetFiles(assetPath, "*.*", SearchOption.AllDirectories).Where(item => { return Path.GetExtension(item) == ".png" || Path.GetExtension(item) == ".jpg"; }); foreach (var path in files) { if(string.IsNullOrEmpty(path))continue; var guid = AssetDatabase.AssetPathToGUID (GetRelativeAssetsPath(path)); AssetFileGuidList.Add(guid); } } /// /// 查找引用 /// void FindReferences(string game) { int startIndex = 0; int count = AssetFileGuidList.Count; string guid = AssetFileGuidList [startIndex]; string curAssetPath = AssetDatabase.GUIDToAssetPath (guid); string findPath = string.Format(FindPath,game); string[] files = Directory.GetFiles(findPath, "*.*", SearchOption.AllDirectories) .Where(s => containsExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray(); int findIndex = 0; bool haveRef = false; EditorApplication.update += delegate() { string file = files [findIndex]; bool isCancel = EditorUtility.DisplayCancelableProgressBar ("查找资源中。。。", curAssetPath.Replace(AssetPath.Replace(Application.dataPath,"Assets")+"/",""), (float)(findIndex+startIndex*files.Length) / (float)(count*files.Length)); if (Regex.IsMatch (File.ReadAllText (file), guid)) { haveRef = true; } findIndex++; if(findIndex>=files.Length) { findIndex = 0; startIndex++; if(!haveRef&&!MatchLuaFiles(curAssetPath,game)){ NoRefAssetGuidList.Add(guid); } haveRef = false; if(startIndex= count) { EditorUtility.ClearProgressBar (); EditorApplication.update = null; findIndex = 0; startIndex = 0; DebugNoRefList(game); DebugDynamicLoadList(game); checkList.Remove(game); if (checkList.Count > 0) { ResetList(); CollectAllAsset(checkList[0]); FindReferences(checkList[0]); } } }; } /// /// 获取资源真实路径 /// private string GetRelativeAssetsPath(string path) { return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/'); } /// /// 打印无引用资源列表 /// void DebugNoRefList(string game) { Debug.Log(string.Format("=============================={0}无引用资源列表Start================================",game)); foreach (var guid in NoRefAssetGuidList) { if (string.IsNullOrEmpty (guid)) continue; Debug.Log (AssetDatabase.GUIDToAssetPath (guid)); } Debug.Log(string.Format("=============================={0}无引用资源列表 End================================\n", game)); } /// /// 打印动态加载资源列表 /// void DebugDynamicLoadList(string game) { if (!isShowDynamicList) return; Debug.Log(string.Format("=============================={0}动态加载资源列表Start================================", game)); DirectoryInfo directoryInfo; foreach (var dic in DynamicLoadAssetList) { if (string.IsNullOrEmpty (dic.Key)) continue; directoryInfo = new DirectoryInfo (dic.Key); Debug.Log (string.Format("Asset:{0} is dynamic load in lua file {1}",directoryInfo.Name,dic.Value)); } Debug.Log(string.Format("=============================={0}动态加载资源列表 End================================\n", game)); } /// /// 匹配lua文件 /// bool MatchLuaFiles(string assetPath,string game) { DirectoryInfo directoryInfo = new DirectoryInfo (assetPath); var assetName = directoryInfo.Name.Replace(".jpg","").Replace(".png",""); var luaFilesPath = string.Format(LuaFilesPath,game); directoryInfo = new DirectoryInfo(luaFilesPath); var dirctoryInfos = directoryInfo.GetDirectories ().Where(item=>!withoutLuaExtensions.Contains(item.Name)); foreach(var info in dirctoryInfos) { if (info == null) continue; var files = Directory.GetFiles (info.FullName, "*.*", SearchOption.AllDirectories); foreach(var file in files) { if (file.EndsWith (".meta")) continue; var text = File.ReadAllText (file); if (Regex.IsMatch (File.ReadAllText (file), assetName)) { DynamicLoadAssetList.Add (assetPath,file); return true; } if(Regex.IsMatch(assetName,"[0-9]{1,}$")){ var str = assetName.Substring(0, assetName.Length - 1); if (Regex.IsMatch(File.ReadAllText(file), str)) { DynamicLoadAssetList.Add(assetPath, file); return true; } } } } return false; } }