| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 | 
							- using System;
 
- using System.IO;
 
- using System.Collections;
 
- using System.Collections.Generic;
 
- using UnityEngine;
 
- using UnityEditor;
 
- using UnityEditor.Animations;
 
- namespace YooAsset.Editor
 
- {
 
- 	public static class AssetBundleBuilderTools
 
- 	{
 
- 		/// <summary>
 
- 		/// 检测所有损坏的预制体文件
 
- 		/// </summary>
 
- 		public static void CheckCorruptionPrefab(List<string> searchDirectorys)
 
- 		{
 
- 			if (searchDirectorys.Count == 0)
 
- 				throw new Exception("路径列表不能为空!");
 
- 			// 获取所有资源列表
 
- 			int checkCount = 0;
 
- 			int invalidCount = 0;
 
- 			string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Prefab, searchDirectorys.ToArray());
 
- 			foreach (string assetPath in findAssets)
 
- 			{
 
- 				UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
 
- 				if (prefab == null)
 
- 				{
 
- 					invalidCount++;
 
- 					Debug.LogError($"发现损坏预制件:{assetPath}");
 
- 				}
 
- 				EditorTools.DisplayProgressBar("检测预制件文件是否损坏", ++checkCount, findAssets.Length);
 
- 			}
 
- 			EditorTools.ClearProgressBar();
 
- 			if (invalidCount == 0)
 
- 				Debug.Log($"没有发现损坏预制件");
 
- 		}
 
- 		/// <summary>
 
- 		/// 检测所有动画控制器的冗余状态
 
- 		/// </summary>
 
- 		public static void FindRedundantAnimationState(List<string> searchDirectorys)
 
- 		{
 
- 			if (searchDirectorys.Count == 0)
 
- 				throw new Exception("路径列表不能为空!");
 
- 			// 获取所有资源列表
 
- 			int checkCount = 0;
 
- 			int findCount = 0;
 
- 			string[] findAssets = EditorTools.FindAssets(EAssetSearchType.RuntimeAnimatorController, searchDirectorys.ToArray());
 
- 			foreach (string assetPath in findAssets)
 
- 			{
 
- 				AnimatorController animator= AssetDatabase.LoadAssetAtPath<AnimatorController>(assetPath);
 
- 				if (FindRedundantAnimationState(animator))
 
- 				{
 
- 					findCount++;
 
- 					Debug.LogWarning($"发现冗余的动画控制器:{assetPath}");
 
- 				}
 
- 				EditorTools.DisplayProgressBar("检测冗余的动画控制器", ++checkCount, findAssets.Length);
 
- 			}
 
- 			EditorTools.ClearProgressBar();
 
- 			if (findCount == 0)
 
- 				Debug.Log($"没有发现冗余的动画控制器");
 
- 			else
 
- 				AssetDatabase.SaveAssets();
 
- 		}
 
- 		/// <summary>
 
- 		/// 清理所有材质球的冗余属性
 
- 		/// </summary>
 
- 		public static void ClearMaterialUnusedProperty(List<string> searchDirectorys)
 
- 		{
 
- 			if (searchDirectorys.Count == 0)
 
- 				throw new Exception("路径列表不能为空!");
 
- 			// 获取所有资源列表
 
- 			int checkCount = 0;
 
- 			int removedCount = 0;
 
- 			string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Material, searchDirectorys.ToArray());
 
- 			foreach (string assetPath in findAssets)
 
- 			{
 
- 				Material mat = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
 
- 				if (ClearMaterialUnusedProperty(mat))
 
- 				{
 
- 					removedCount++;
 
- 					Debug.LogWarning($"材质球已被处理:{assetPath}");
 
- 				}
 
- 				EditorTools.DisplayProgressBar("清理冗余的材质球", ++checkCount, findAssets.Length);
 
- 			}
 
- 			EditorTools.ClearProgressBar();
 
- 			if (removedCount == 0)
 
- 				Debug.Log($"没有发现冗余的材质球");
 
- 			else
 
- 				AssetDatabase.SaveAssets();
 
- 		}
 
- 		/// <summary>
 
- 		/// 清理无用的材质球属性
 
- 		/// </summary>
 
- 		private static bool ClearMaterialUnusedProperty(Material mat)
 
- 		{
 
- 			bool removeUnused = false;
 
- 			SerializedObject so = new SerializedObject(mat);
 
- 			SerializedProperty sp = so.FindProperty("m_SavedProperties");
 
- 			sp.Next(true);
 
- 			do
 
- 			{
 
- 				if (sp.isArray == false)
 
- 					continue;
 
- 				for (int i = sp.arraySize - 1; i >= 0; --i)
 
- 				{
 
- 					var p1 = sp.GetArrayElementAtIndex(i);
 
- 					if (p1.isArray)
 
- 					{
 
- 						for (int ii = p1.arraySize - 1; ii >= 0; --ii)
 
- 						{
 
- 							var p2 = p1.GetArrayElementAtIndex(ii);
 
- 							var val = p2.FindPropertyRelative("first");
 
- 							if (mat.HasProperty(val.stringValue) == false)
 
- 							{
 
- 								Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
 
- 								p1.DeleteArrayElementAtIndex(ii);
 
- 								removeUnused = true;
 
- 							}
 
- 						}
 
- 					}
 
- 					else
 
- 					{
 
- 						var val = p1.FindPropertyRelative("first");
 
- 						if (mat.HasProperty(val.stringValue) == false)
 
- 						{
 
- 							Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
 
- 							sp.DeleteArrayElementAtIndex(i);
 
- 							removeUnused = true;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			while (sp.Next(false));
 
- 			so.ApplyModifiedProperties();
 
- 			return removeUnused;
 
- 		}
 
- 		/// <summary>
 
- 		/// 查找动画控制器里冗余的动画状态机
 
- 		/// </summary>
 
- 		private static bool FindRedundantAnimationState(AnimatorController animatorController)
 
- 		{
 
- 			if (animatorController == null)
 
- 				return false;
 
- 			string assetPath = AssetDatabase.GetAssetPath(animatorController);
 
- 			// 查找使用的状态机名称
 
- 			List<string> usedStateNames = new List<string>();
 
- 			foreach (var layer in animatorController.layers)
 
- 			{
 
- 				foreach (var state in layer.stateMachine.states)
 
- 				{
 
- 					usedStateNames.Add(state.state.name);
 
- 				}
 
- 			}
 
- 			List<string> allLines = new List<string>();
 
- 			List<int> stateIndexList = new List<int>();
 
- 			using (StreamReader reader = File.OpenText(assetPath))
 
- 			{
 
- 				string content;
 
- 				while (null != (content = reader.ReadLine()))
 
- 				{
 
- 					allLines.Add(content);
 
- 					if (content.StartsWith("AnimatorState:"))
 
- 					{
 
- 						stateIndexList.Add(allLines.Count - 1);
 
- 					}
 
- 				}
 
- 			}
 
- 			List<string> allStateNames = new List<string>();
 
- 			foreach (var index in stateIndexList)
 
- 			{
 
- 				for (int i = index; i < allLines.Count; i++)
 
- 				{
 
- 					string content = allLines[i];
 
- 					content = content.Trim();
 
- 					if (content.StartsWith("m_Name"))
 
- 					{
 
- 						string[] splits = content.Split(':');
 
- 						string name = splits[1].TrimStart(' '); //移除前面的空格
 
- 						allStateNames.Add(name);
 
- 						break;
 
- 					}
 
- 				}
 
- 			}
 
- 			bool foundRedundantState = false;
 
- 			foreach (var stateName in allStateNames)
 
- 			{
 
- 				if (usedStateNames.Contains(stateName) == false)
 
- 				{
 
- 					Debug.LogWarning($"发现冗余的动画文件:{assetPath}={stateName}");
 
- 					foundRedundantState = true;
 
- 				}
 
- 			}
 
- 			return foundRedundantState;
 
- 		}
 
- 	}
 
- }
 
 
  |