1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
| #region classname
#endregion using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; namespace Ufw { public class UnusedKeywordsAndPropertiesCheckerEditor : Editor { private static bool GetShaderKeywords(Shader target, out string[] global, out string[] local) { try { MethodInfo globalKeywords = typeof(ShaderUtil).GetMethod("GetShaderGlobalKeywords", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo localKeywords = typeof(ShaderUtil).GetMethod("GetShaderLocalKeywords", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (globalKeywords != null) { global = (string[])globalKeywords.Invoke(null, new object[] { target }); } else { global = null; } if (localKeywords != null) { local = (string[])localKeywords.Invoke(null, new object[] { target }); } else { local = null; } return true; } catch (Exception e) { Log.Error($"获取shader中所有的宏,错误: {e.Message}"); global = local = null; return false; } } [MenuItem(UfwMenuItemIni.M_Check_MatKey)] public static void CheckMaterials() { EditorUtility.ClearProgressBar(); ProfilerUtils.BeginWatch("CheckMaterials"); string[] paths = AssetDatabase.FindAssets("t:material", new[] { "Assets/Res" }); if (paths == null || paths.Length == 0) { Log.Info($"未找到相匹配的文件 匹配格式: t:material 匹配路径: Assets/Res"); return; } int index = 0; int maxCount = paths.Length; foreach (string materialGuid in paths) { string materialAssetPath = AssetDatabase.GUIDToAssetPath(materialGuid); Material material = AssetDatabase.LoadAssetAtPath<Material>(materialAssetPath); EditorUtility.DisplayProgressBar($"读取文件Material文件: {material.name}", $"正在查询内容", (float)index / maxCount); if (GetShaderKeywords(material.shader, out string[] global, out string[] local)) { HashSet<string> keywords = new HashSet<string>(); if (global != null) { foreach (string g in global) { keywords.Add(g); } } if (local != null) { foreach (string l in local) { keywords.Add(l); } } if (keywords.Count == 0) { Log.Warn($"读取文件失效,请检查Material: {material.name} Shader: {material.shader}"); continue; } EditorUtility.ClearProgressBar(); List<string> resetKeywords = new List<string>(material.shaderKeywords); int removeIndex = 0; foreach (string item in material.shaderKeywords) { EditorUtility.DisplayProgressBar($"检查KeyWords: {material.name}", $"匹配字段 {item}", (float)removeIndex / resetKeywords.Count); if (!keywords.Contains(item)) { resetKeywords.Remove(item); } removeIndex++; } material.shaderKeywords = resetKeywords.ToArray(); } else { Log.Warn($"获取shader中所有的宏,Error: Material:{material.name} shader:{material.shader}"); continue; } EditorUtility.ClearProgressBar(); HashSet<string> property = new HashSet<string>(); int count = material.shader.GetPropertyCount(); for (int i = 0; i < count; i++) { property.Add(material.shader.GetPropertyName(i)); } SerializedObject o = new SerializedObject(material); SerializedProperty disabledShaderPasses = o.FindProperty("disabledShaderPasses"); SerializedProperty savedProperties = o.FindProperty("m_SavedProperties"); SerializedProperty texEnvs = savedProperties.FindPropertyRelative("m_TexEnvs"); SerializedProperty floats = savedProperties.FindPropertyRelative("m_Floats"); SerializedProperty colors = savedProperties.FindPropertyRelative("m_Colors"); int removeAttrId = 0; int removeAttrCount = disabledShaderPasses.arraySize + texEnvs.arraySize + floats.arraySize + colors.arraySize; EditorUtility.ClearProgressBar(); for (int i = disabledShaderPasses.arraySize - 1; i >= 0; i--) { string displayName = disabledShaderPasses.GetArrayElementAtIndex(i).displayName; EditorUtility.DisplayProgressBar($"{material.name} 对比:disabledShaderPasses", $"检查属性{displayName}", (float)removeAttrId / removeAttrCount); if (!property.Contains(displayName)) { disabledShaderPasses.DeleteArrayElementAtIndex(i); } removeAttrId++; } EditorUtility.ClearProgressBar(); for (int i = texEnvs.arraySize - 1; i >= 0; i--) { string displayName = texEnvs.GetArrayElementAtIndex(i).displayName; EditorUtility.DisplayProgressBar($"{material.name} 对比:m_TexEnvs", $"检查属性{displayName}", (float)removeAttrId / removeAttrCount); if (!property.Contains(displayName)) { texEnvs.DeleteArrayElementAtIndex(i); } removeAttrId++; } EditorUtility.ClearProgressBar(); for (int i = floats.arraySize - 1; i >= 0; i--) { string displayName = floats.GetArrayElementAtIndex(i).displayName; EditorUtility.DisplayProgressBar($"{material.name} 对比:m_Floats", $"检查属性{displayName}", (float)removeAttrId / removeAttrCount); if (!property.Contains(displayName)) { floats.DeleteArrayElementAtIndex(i); } removeAttrId++; } EditorUtility.ClearProgressBar(); for (int i = colors.arraySize - 1; i >= 0; i--) { string displayName = colors.GetArrayElementAtIndex(i).displayName; EditorUtility.DisplayProgressBar($"{material.name} 对比:m_Colors", $"检查属性{displayName}", (float)removeAttrId / removeAttrCount); if (!property.Contains(displayName)) { colors.DeleteArrayElementAtIndex(i); } removeAttrId++; } o.ApplyModifiedProperties(); index += 1; } UWatchResult result = ProfilerUtils.EndWatch("CheckMaterials"); Log.Info($"清理Material残留 时间{result.costTime} [内存]{result.costMemory}"); EditorUtility.ClearProgressBar(); AssetDatabase.SaveAssets(); Log.Info("检查完毕"); } } }
|