时间2026.07版本Unity 6000.3.19f1打包前预处理using UnityEditor; using UnityEditor.Build; using UnityEditor.Build.Reporting; using UnityEngine; public class InitializeBeforeBuild : IPreprocessBuildWithReport { public int callbackOrder 0; // 执行顺序数值越小越先执行 public void OnPreprocessBuild(BuildReport report) { // TODO预处理内容例如设置项目名称等 PlayerSettings.productName MyProject; // 项目名称 Debug.Log($Build Product Name set to: {PlayerSettings.productName}); } }清空控制台日志using System; using System.Reflection; using UnityEditor; using UnityEngine; public class MyEditor : Editor { [MenuItem(Tools/Clear Console Log)] public static void ClearConsoleLog() { try { string LogEntries UnityEditor.LogEntries; Assembly assembly typeof(EditorWindow).Assembly; Type logEntriesType assembly.GetType(LogEntries); if (logEntriesType ! null) { BindingFlags bindingFlags BindingFlags.Static | BindingFlags.Public; MethodInfo clearMethod logEntriesType.GetMethod(Clear, bindingFlags); clearMethod?.Invoke(null, null); Debug.Log(控制台日志已成功清空); } } catch (Exception e) { Debug.LogError($清空日志失败: {e.Message}); } } }查找指定脚本0using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; public class MyEditor : EditorWindow { private MonoScript targetScript; private ListGameObject foundObjects new ListGameObject(); private Liststring foundPaths new Liststring(); private Vector2 scrollPosition; private bool includeInactive true; private string searchFilter ; private bool searchInProgress; [MenuItem(RicKotel/Windows/Finder Appoint Script)] public static void ShowWindow() { GetWindowMyEditor(Finder Appoint Script); } private void OnGUI() { EditorGUILayout.HelpBox(查找挂载特定脚本的对象, MessageType.Info); // 目标脚本选择 EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(目标脚本:, GUILayout.Width(60)); targetScript (MonoScript)EditorGUILayout.ObjectField(targetScript, typeof(MonoScript), false); EditorGUILayout.EndHorizontal(); // 搜索选项 EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(过滤对象名字:, GUILayout.Width(85)); searchFilter EditorGUILayout.TextField(, searchFilter); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(包含未激活对象:, GUILayout.Width(100)); includeInactive EditorGUILayout.Toggle(, includeInactive); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 功能按钮 EditorGUILayout.BeginHorizontal(); GUI.enabled targetScript ! null !searchInProgress; if (GUILayout.Button(检查选定对象)) { SearchSelectedObjects(); } if (GUILayout.Button(检查当前场景)) { SearchCurrentScene(); } if (GUILayout.Button(检查所有预制体)) { SearchAllPrefabs(); } GUI.enabled true; if (GUILayout.Button(重置)) { searchInProgress false; } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 结果显示 if (searchInProgress) { EditorGUILayout.LabelField(正在搜索...); } else if (foundObjects.Count 0) { EditorGUILayout.LabelField($发现 {foundObjects.Count} 个匹配对象:, EditorStyles.boldLabel); // 批量操作按钮 EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(选择全部)) { Selection.objects foundObjects.ToArray(); } if (GUILayout.Button(复制列表)) { CopyResultsToClipboard(); } if (GUILayout.Button(清除结果)) { ClearResults(); } EditorGUILayout.EndHorizontal(); // 列表显示 scrollPosition EditorGUILayout.BeginScrollView(scrollPosition); for (int i 0; i foundObjects.Count; i) { if (!string.IsNullOrEmpty(searchFilter) !foundPaths[i].ToLower().Contains(searchFilter.ToLower())) { continue; } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(foundPaths[i], EditorStyles.label)) { SelectObject(foundObjects[i]); } // 显示对象类型标记 string typeLabel GetObjectTypeLabel(foundObjects[i]); GUILayout.Label(typeLabel, GUILayout.Width(60)); EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } else if (targetScript ! null) { EditorGUILayout.LabelField(没有找到匹配的对象); } } private void SearchSelectedObjects() { if (targetScript null) { EditorUtility.DisplayDialog(错误, 请先选择目标脚本, 确定); return; } ClearResults(); searchInProgress true; Repaint(); GameObject[] selectedObjects Selection.gameObjects; if (selectedObjects.Length 0) { EditorUtility.DisplayDialog(提示, 请先选择场景中的对象, 确定); searchInProgress false; return; } System.Type scriptType targetScript.GetClass(); if (scriptType null) { EditorUtility.DisplayDialog(错误, 无法获取脚本类型请确保脚本已编译, 确定); searchInProgress false; return; } foreach (GameObject go in selectedObjects) { FindScriptInGameObject(go, scriptType); } searchInProgress false; ShowNotification(new GUIContent($搜索完成发现 {foundObjects.Count} 个匹配对象)); } private void SearchCurrentScene() { if (targetScript null) { EditorUtility.DisplayDialog(错误, 请先选择目标脚本, 确定); return; } ClearResults(); searchInProgress true; Repaint(); System.Type scriptType targetScript.GetClass(); if (scriptType null) { EditorUtility.DisplayDialog(错误, 无法获取脚本类型请确保脚本已编译, 确定); searchInProgress false; return; } GameObject[] allObjects includeInactive ? Resources.FindObjectsOfTypeAllGameObject() : GameObject.FindObjectsByTypeGameObject(FindObjectsInactive.Include, FindObjectsSortMode.InstanceID); foreach (GameObject go in allObjects) { // 跳过预制体资源只检查场景实例 if (AssetDatabase.Contains(go)) continue; FindScriptInGameObject(go, scriptType); } searchInProgress false; ShowNotification(new GUIContent($搜索完成发现 {foundObjects.Count} 个匹配对象)); } private void SearchAllPrefabs() { if (targetScript null) { EditorUtility.DisplayDialog(错误, 请先选择目标脚本, 确定); return; } ClearResults(); searchInProgress true; Repaint(); System.Type scriptType targetScript.GetClass(); if (scriptType null) { EditorUtility.DisplayDialog(错误, 无法获取脚本类型请确保脚本已编译, 确定); searchInProgress false; return; } string[] prefabGuids AssetDatabase.FindAssets(t:Prefab); int processed 0; foreach (string guid in prefabGuids) { string path AssetDatabase.GUIDToAssetPath(guid); GameObject prefab AssetDatabase.LoadAssetAtPathGameObject(path); if (prefab ! null) { FindScriptInGameObject(prefab, scriptType, path); } processed; if (processed % 50 0) // 每处理50个更新一次UI避免卡死 { EditorUtility.DisplayProgressBar(搜索预制体, $正在处理 {processed}/{prefabGuids.Length}, (float)processed / prefabGuids.Length); Repaint(); } } EditorUtility.ClearProgressBar(); searchInProgress false; ShowNotification(new GUIContent($搜索完成发现 {foundObjects.Count} 个匹配对象)); } private void FindScriptInGameObject(GameObject go, System.Type scriptType, string assetPath null) { if (scriptType.BaseType.Name.Contains(Editor)) return; // 检查当前对象 Component component go.GetComponent(scriptType); if (component ! null !foundObjects.Contains(go)) { foundObjects.Add(go); foundPaths.Add(GetFullPath(go, assetPath)); } // 检查子对象 foreach (Transform child in go.transform) { FindScriptInGameObject(child.gameObject, scriptType, assetPath); } } private string GetFullPath(GameObject go, string assetPath null) { StringBuilder pathBuilder new StringBuilder(); Transform current go.transform; while (current ! null) { pathBuilder.Insert(0, / current.name); current current.parent; } if (!string.IsNullOrEmpty(assetPath)) { return $[预制体: {assetPath}] {pathBuilder}; } return pathBuilder.ToString(); } private string GetObjectTypeLabel(GameObject go) { if (PrefabUtility.IsPartOfPrefabInstance(go)) { return (实例); } else if (AssetDatabase.Contains(go)) { return (预制体); } else { return (场景); } } private void SelectObject(GameObject go) { // 如果是预制体资源在Project窗口选中 if (AssetDatabase.Contains(go)) { EditorUtility.FocusProjectWindow(); Selection.activeObject go; EditorGUIUtility.PingObject(go); } else // 如果是场景对象在Hierarchy窗口选中 { // 确保对象是活跃的如果是未激活的父对象的子对象 SetParentsActive(go); Selection.activeGameObject go; EditorGUIUtility.PingObject(go); // 如果是预制体实例同时选中预制体资源 if (PrefabUtility.IsPartOfPrefabInstance(go)) { Object prefabRoot PrefabUtility.GetCorrespondingObjectFromSource(go); EditorGUIUtility.PingObject(prefabRoot); } } } private void SetParentsActive(GameObject go) { Transform parent go.transform.parent; while (parent ! null) { parent.gameObject.SetActive(true); parent parent.parent; } } private void CopyResultsToClipboard() { StringBuilder sb new StringBuilder(); for (int i 0; i foundObjects.Count; i) { sb.AppendLine(foundPaths[i]); } EditorGUIUtility.systemCopyBuffer sb.ToString(); ShowNotification(new GUIContent(已复制到剪贴板)); } private void ClearResults() { foundObjects.Clear(); foundPaths.Clear(); } }查找丢失脚本using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; public class MyEditor : EditorWindow { private ListGameObject missingScriptObjects new ListGameObject(); private Liststring missingScriptPaths new Liststring(); private Vector2 scrollPosition; private bool includeInactive true; private string searchFilter ; [MenuItem(RicKotel/Windows/Finder Missing Script)] public static void ShowWindow() { GetWindowMyEditor(Finder Missing Script); } private void OnGUI() { EditorGUILayout.HelpBox(查找并定位带有丢失脚本的对象, MessageType.Info); // 搜索选项 EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(过滤对象名字:, GUILayout.Width(85)); searchFilter EditorGUILayout.TextField(, searchFilter); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(包含未激活对象:, GUILayout.Width(100)); includeInactive EditorGUILayout.Toggle(, includeInactive); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 功能按钮 EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(检查选定对象)) { CheckSelectedObjects(); } if (GUILayout.Button(检查当前场景)) { CheckCurrentScene(); } if (GUILayout.Button(检查所有预制体)) { CheckAllPrefabs(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 结果显示 if (missingScriptObjects.Count 0) { EditorGUILayout.LabelField($发现 {missingScriptObjects.Count} 个丢失脚本:, EditorStyles.boldLabel); // 批量操作按钮 EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(选择全部)) { Selection.objects missingScriptObjects.ToArray(); } if (GUILayout.Button(移除选中对象的丢失脚本)) { RemoveMissingScriptsFromSelection(); } if (GUILayout.Button(清除列表)) { missingScriptObjects.Clear(); missingScriptPaths.Clear(); } EditorGUILayout.EndHorizontal(); // 列表显示 scrollPosition EditorGUILayout.BeginScrollView(scrollPosition); for (int i 0; i missingScriptObjects.Count; i) { if (!string.IsNullOrEmpty(searchFilter) !missingScriptPaths[i].ToLower().Contains(searchFilter.ToLower())) { continue; } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(missingScriptPaths[i], EditorStyles.label)) { SelectObject(missingScriptObjects[i]); } // 显示场景/预制体标记 if (PrefabUtility.IsPartOfPrefabInstance(missingScriptObjects[i])) { GUILayout.Label((Prefab), GUILayout.Width(60)); } else if (AssetDatabase.Contains(missingScriptObjects[i])) { GUILayout.Label((Asset), GUILayout.Width(60)); } else { GUILayout.Label((Scene), GUILayout.Width(60)); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } else { EditorGUILayout.LabelField(没有发现丢失脚本); } } private void CheckSelectedObjects() { ClearResults(); GameObject[] selectedObjects Selection.gameObjects; if (selectedObjects.Length 0) { EditorUtility.DisplayDialog(提示, 请先选择场景中的对象, 确定); return; } foreach (GameObject go in selectedObjects) { FindMissingScriptsInGameObject(go); } ShowNotification(new GUIContent($检查完成发现 {missingScriptObjects.Count} 个丢失脚本)); } private void CheckCurrentScene() { ClearResults(); GameObject[] allObjects includeInactive ? Resources.FindObjectsOfTypeAllGameObject() : GameObject.FindObjectsByTypeGameObject(FindObjectsInactive.Include, FindObjectsSortMode.InstanceID); foreach (GameObject go in allObjects) { // 跳过预制体资源只检查场景实例 if (AssetDatabase.Contains(go)) continue; FindMissingScriptsInGameObject(go); } ShowNotification(new GUIContent($检查完成发现 {missingScriptObjects.Count} 个丢失脚本)); } private void CheckAllPrefabs() { ClearResults(); string[] prefabGuids AssetDatabase.FindAssets(t:Prefab); foreach (string guid in prefabGuids) { string path AssetDatabase.GUIDToAssetPath(guid); GameObject prefab AssetDatabase.LoadAssetAtPathGameObject(path); if (prefab ! null) { FindMissingScriptsInGameObject(prefab, path); } } ShowNotification(new GUIContent($检查完成发现 {missingScriptObjects.Count} 个丢失脚本)); } private void FindMissingScriptsInGameObject(GameObject go, string assetPath null) { // 检查当前对象 Component[] components go.GetComponentsComponent(); bool hasMissing false; foreach (Component component in components) { if (component null) { hasMissing true; break; } } if (hasMissing !missingScriptObjects.Contains(go)) { missingScriptObjects.Add(go); missingScriptPaths.Add(GetFullPath(go, assetPath)); } // 检查子对象 foreach (Transform child in go.transform) { FindMissingScriptsInGameObject(child.gameObject, assetPath); } } private string GetFullPath(GameObject go, string assetPath null) { StringBuilder pathBuilder new StringBuilder(); Transform current go.transform; while (current ! null) { pathBuilder.Insert(0, / current.name); current current.parent; } if (!string.IsNullOrEmpty(assetPath)) { return $[预制体: {assetPath}] {pathBuilder}; } return pathBuilder.ToString(); } private void SelectObject(GameObject go) { // 如果是预制体资源在Project窗口选中 if (AssetDatabase.Contains(go)) { EditorUtility.FocusProjectWindow(); Selection.activeObject go; } else // 如果是场景对象在Hierarchy窗口选中 { EditorUtility.FocusProjectWindow(); Selection.activeGameObject go; EditorGUIUtility.PingObject(go); // 如果是预制体实例同时选中预制体资源 if (PrefabUtility.IsPartOfPrefabInstance(go)) { Object prefabRoot PrefabUtility.GetCorrespondingObjectFromSource(go); EditorGUIUtility.PingObject(prefabRoot); } } } private void RemoveMissingScriptsFromSelection() { if (missingScriptObjects.Count 0) return; int totalRemoved 0; Undo.RecordObjects(missingScriptObjects.ToArray(), Remove missing scripts); foreach (GameObject go in missingScriptObjects) { // 跳过预制体资源只能在场景实例上移除 if (!AssetDatabase.Contains(go)) { int removed GameObjectUtility.RemoveMonoBehavioursWithMissingScript(go); totalRemoved removed; } } EditorUtility.DisplayDialog(完成, $已移除 {totalRemoved} 个丢失脚本, 确定); ClearResults(); } private void ClearResults() { missingScriptObjects.Clear(); missingScriptPaths.Clear(); } }查找丢失网格using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; public class MyEditor : EditorWindow { private ListGameObject missingMeshObjects new ListGameObject(); private Vector2 scrollPosition; private bool autoSelect true; private bool showMeshFilters true; private bool showSkinnedMeshes true; private bool showPrefabs true; private bool showSceneObjects true; private string searchFilter ; [MenuItem(RicKotel/Windows/Finder Missing Mesh)] public static void ShowWindow() { var window GetWindowMyEditor(丢失网格查找器); window.minSize new Vector2(400, 300); window.RefreshMissingMeshes(); } private void OnGUI() { DrawToolbar(); DrawMainView(); DrawStatusBar(); } private void DrawToolbar() { GUILayout.BeginHorizontal(EditorStyles.toolbar); if (GUILayout.Button(刷新, EditorStyles.toolbarButton)) { RefreshMissingMeshes(); } autoSelect GUILayout.Toggle(autoSelect, 自动选择, EditorStyles.toolbarButton); GUILayout.FlexibleSpace(); showMeshFilters GUILayout.Toggle(showMeshFilters, 网格过滤器, EditorStyles.toolbarButton); showSkinnedMeshes GUILayout.Toggle(showSkinnedMeshes, 蒙皮网格, EditorStyles.toolbarButton); showPrefabs GUILayout.Toggle(showPrefabs, Prefabs, EditorStyles.toolbarButton); showSceneObjects GUILayout.Toggle(showSceneObjects, 场景对象, EditorStyles.toolbarButton); GUILayout.EndHorizontal(); // 搜索框 GUILayout.BeginHorizontal(EditorStyles.toolbar); GUILayout.Label(搜索:, GUILayout.Width(40)); searchFilter GUILayout.TextField(searchFilter, EditorStyles.toolbarSearchField); GUILayout.EndHorizontal(); } private void DrawMainView() { scrollPosition GUILayout.BeginScrollView(scrollPosition); var filteredObjects missingMeshObjects .Where(go string.IsNullOrEmpty(searchFilter) || go.name.ToLower().Contains(searchFilter.ToLower())) .ToList(); foreach (var obj in filteredObjects) { if (obj null) continue; // 处理可能已被销毁的对象 bool isPrefab PrefabUtility.IsPartOfAnyPrefab(obj); if ((isPrefab !showPrefabs) || (!isPrefab !showSceneObjects)) continue; GUILayout.BeginHorizontal(); // 显示对象类型图标 GUIContent content new GUIContent( obj.name, EditorGUIUtility.ObjectContent(obj, obj.GetType()).image); if (GUILayout.Button(content, EditorStyles.label, GUILayout.Height(24))) { Selection.activeGameObject obj; EditorGUIUtility.PingObject(obj); } GUILayout.FlexibleSpace(); // 显示问题组件 var problems GetMissingComponents(obj); GUILayout.Label(string.Join(, , problems), EditorStyles.miniLabel); // 修复按钮 if (GUILayout.Button(修复, EditorStyles.miniButton, GUILayout.Width(50))) { FixMissingMesh(obj); } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); } private void DrawStatusBar() { GUILayout.BeginHorizontal(EditorStyles.helpBox); GUILayout.Label($找到 {missingMeshObjects.Count} 个问题对象); GUILayout.FlexibleSpace(); if (GUILayout.Button(全部选择, EditorStyles.miniButton)) { Selection.objects missingMeshObjects.Where(go go ! null).ToArray(); } if (GUILayout.Button(全部修复, EditorStyles.miniButton)) { if (EditorUtility.DisplayDialog(确认, 确定要尝试修复所有丢失的网格吗, 修复, 取消)) { foreach (var obj in missingMeshObjects.Where(go go ! null)) { FixMissingMesh(obj); } RefreshMissingMeshes(); } } GUILayout.EndHorizontal(); } private void RefreshMissingMeshes() { missingMeshObjects.Clear(); // 查找场景中的对象 if (showSceneObjects) { var sceneObjects Resources.FindObjectsOfTypeAllGameObject() .Where(go go.hideFlags HideFlags.None !EditorUtility.IsPersistent(go)); foreach (var go in sceneObjects) { CheckGameObject(go); } } // 查找Prefab中的对象 if (showPrefabs) { var prefabPaths AssetDatabase.GetAllAssetPaths() .Where(path path.EndsWith(.prefab)); foreach (var path in prefabPaths) { var prefab AssetDatabase.LoadAssetAtPathGameObject(path); if (prefab ! null) { CheckGameObject(prefab); } } } // 自动选择第一个对象 if (autoSelect missingMeshObjects.Count 0) { Selection.activeGameObject missingMeshObjects[0]; EditorGUIUtility.PingObject(missingMeshObjects[0]); } } private void CheckGameObject(GameObject go) { bool hasProblem false; // 检查MeshFilter if (showMeshFilters) { var meshFilter go.GetComponentMeshFilter(); if (meshFilter ! null meshFilter.sharedMesh null) { hasProblem true; } } // 检查SkinnedMeshRenderer if (showSkinnedMeshes) { var skinnedMesh go.GetComponentSkinnedMeshRenderer(); if (skinnedMesh ! null skinnedMesh.sharedMesh null) { hasProblem true; } } if (hasProblem) { missingMeshObjects.Add(go); } } private Liststring GetMissingComponents(GameObject go) { var problems new Liststring(); var meshFilter go.GetComponentMeshFilter(); if (meshFilter ! null meshFilter.sharedMesh null) { problems.Add(MeshFilter丢失网格); } var skinnedMesh go.GetComponentSkinnedMeshRenderer(); if (skinnedMesh ! null skinnedMesh.sharedMesh null) { problems.Add(SkinnedMeshRenderer丢失网格); } return problems; } private void FixMissingMesh(GameObject go) { bool fixedSomething false; Undo.RecordObject(go, 修复丢失网格); // 修复MeshFilter var meshFilter go.GetComponentMeshFilter(); if (meshFilter ! null meshFilter.sharedMesh null) { meshFilter.sharedMesh GetDefaultMesh(); fixedSomething true; } // 修复SkinnedMeshRenderer var skinnedMesh go.GetComponentSkinnedMeshRenderer(); if (skinnedMesh ! null skinnedMesh.sharedMesh null) { skinnedMesh.sharedMesh GetDefaultMesh(); fixedSomething true; } if (fixedSomething) { EditorUtility.SetDirty(go); Debug.Log($已修复 {go.name} 的丢失网格, go); } else { Debug.LogWarning(${go.name} 没有需要修复的问题, go); } } private Mesh GetDefaultMesh() { // 尝试获取内置立方体网格 var defaultMesh Resources.GetBuiltinResourceMesh(Cube.fbx); // 如果找不到内置网格创建一个新网格 if (defaultMesh null) { Debug.LogWarning(无法找到内置默认网格将创建一个新网格); defaultMesh new Mesh { name DefaultMesh }; } return defaultMesh; } }统计文件数量using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; public class MyEditor : EditorWindow { private Vector2 scrollPosition; private string searchFilter ; private string searchFolder Assets; private Dictionarystring, int fileTypeCounts new Dictionarystring, int(); [MenuItem(Tools/统计文件数量)] public static void ShowWindow() { GetWindowMyEditor(Finder Appoint Files); } private void OnGUI() { EditorGUILayout.HelpBox(统计项目中各种类型文件的数量, MessageType.Info); EditorGUILayout.Space(); // 输入要搜索的文件夹路径 EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(搜索文件夹:, GUILayout.Width(80)); var height GUILayout.Height(EditorGUIUtility.singleLineHeight); EditorGUILayout.SelectableLabel(searchFolder, EditorStyles.textField, height); HandleDragAndDrop(); // 处理拖拽事件通过拖拽指定文件夹 SelctionFolder(); // 选择文件夹按钮事件 } EditorGUILayout.EndHorizontal(); // 搜索过滤 EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(过滤:, GUILayout.Width(40)); searchFilter EditorGUILayout.TextField(searchFilter); if (GUILayout.Button(刷新统计, GUILayout.Width(80))) { if (string.IsNullOrEmpty(searchFolder)) searchFolder Assets; CountFileTypes(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); // 结果显示 if (fileTypeCounts.Count 0) { EditorGUILayout.LabelField($在文件夹【{searchFolder}】中共发现 {fileTypeCounts.Values.Sum()} 个文件{fileTypeCounts.Count} 种类型:, EditorStyles.boldLabel); scrollPosition EditorGUILayout.BeginScrollView(scrollPosition); // 按键名排序升序 var sortedItems fileTypeCounts.OrderBy(pair pair.Key); //// 按数量排序降序 //var sortedItems fileTypeCounts.OrderByDescending(pair pair.Value); foreach (var item in sortedItems) { if (!string.IsNullOrEmpty(searchFilter) !item.Key.ToLower().Contains(searchFilter.ToLower())) { continue; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(item.Key, GUILayout.Width(200)); EditorGUILayout.LabelField(item.Value.ToString(), EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } else { EditorGUILayout.LabelField(没有找到文件统计数据); } } private void OnFocus() { CountFileTypes(); } private void HandleDragAndDrop() { Rect dropArea GUILayoutUtility.GetLastRect(); if (Event.current.type EventType.DragUpdated dropArea.Contains(Event.current.mousePosition)) { DragAndDrop.visualMode DragAndDropVisualMode.Copy; Event.current.Use(); } else if (Event.current.type EventType.DragPerform dropArea.Contains(Event.current.mousePosition)) { DragAndDrop.AcceptDrag(); if (DragAndDrop.paths ! null DragAndDrop.paths.Length 0) { string path DragAndDrop.paths[0]; if (Directory.Exists(path)) { // 转换为Assets相对路径 if (path.StartsWith(Application.dataPath)) { searchFolder Assets path.Substring(Application.dataPath.Length); } else { searchFolder path; } CountFileTypes(); } } Event.current.Use(); } } private void SelctionFolder() { if (GUILayout.Button(选择文件夹, GUILayout.Width(100))) { string folderPath EditorUtility.OpenFolderPanel(选择文件夹, Assets, ); if (!string.IsNullOrEmpty(folderPath)) { // 转换为相对路径 if (folderPath.StartsWith(Application.dataPath)) { searchFolder Assets folderPath.Substring(Application.dataPath.Length); CountFileTypes(); } } } } private void CountFileTypes() { fileTypeCounts.Clear(); // 获取项目中所有资源路径 string[] allAssetPaths AssetDatabase.GetAllAssetPaths(); foreach (string path in allAssetPaths) { // 跳过目录和特殊文件 if (path.StartsWith(searchFolder) !Directory.Exists(path)) { string extension Path.GetExtension(path).ToLower(); if (string.IsNullOrEmpty(extension)) { extension [无扩展名]; } if (fileTypeCounts.ContainsKey(extension)) { fileTypeCounts[extension]; } else { fileTypeCounts.Add(extension, 1); } } } // 添加一些Unity特殊类型的统计 CountSpecificTypeTexture2D(Texture2D); CountSpecificTypeMaterial(Material); CountSpecificTypeGameObject(Prefab); CountSpecificTypeShader(Shader); CountSpecificTypeMonoScript(Script); CountSpecificTypeAnimationClip(AnimationClip); CountSpecificTypeAudioClip(AudioClip); } private void CountSpecificTypeT(string typeName) where T : Object { string filter $t:{typeof(T).Name}; string[] searchInFolders new string[] { searchFolder }; string[] guids AssetDatabase.FindAssets(filter, searchInFolders); if (guids.Length 0) // 数量为0的文件类型不统计数量 fileTypeCounts[$[{typeName}]] guids.Length; } }