随着时间的堆积,项目中Assets文件夹下的资源会变得越来越繁杂,有些贴图、材质啥的可能压根没有使用过,但是又不敢轻易去删除。
这里分享两个插件,用于管理这些资源。
一、ResourceChecker
这个插件的强大之处就在于它能够查找当前场景中的所有引用个资源,并快速定位,然后把未定位到的资源手动删掉就行了。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 // Resource Checker 2 // (c) 2012 Simon Oliver / HandCircus / hello@handcircus.com 3 // (c) 2015 Brice Clocher / Mangatome / hello@mangatome.net 4 // Public domain, do with whatever you like, commercial or not 5 // This comes with no warranty, use at your own risk! 6 // https://github.com/handcircus/Unity-Resource-Checker 7 8 using System; 9 using System.Linq; 10 using UnityEngine; 11 using UnityEngine.UI; 12 using UnityEditor; 13 using System.Collections.Generic; 14 using System.Reflection; 15 using Object = UnityEngine.Object; 16 17 public class TextureDetails : IEquatable<TextureDetails> 18 { 19 public bool isCubeMap; 20 public int memSizeKB; 21 public Texture texture; 22 public TextureFormat format; 23 public int mipMapCount; 24 public List<Object> FoundInMaterials=new List<Object>(); 25 public List<Object> FoundInRenderers=new List<Object>(); 26 public List<Object> FoundInAnimators = new List<Object>(); 27 public List<Object> FoundInScripts = new List<Object>(); 28 public List<Object> FoundInGraphics = new List<Object>(); 29 public bool isSky; 30 public bool instance; 31 public bool isgui; 32 public TextureDetails() 33 { 34 35 } 36 37 public bool Equals(TextureDetails other) 38 { 39 return texture != null && other.texture != null && 40 texture.GetNativeTexturePtr() == other.texture.GetNativeTexturePtr(); 41 } 42 43 public override int GetHashCode() 44 { 45 return (int)texture.GetNativeTexturePtr(); 46 } 47 48 public override bool Equals(object obj) 49 { 50 return Equals(obj as TextureDetails); 51 } 52 }; 53 54 public class MaterialDetails 55 { 56 57 public Material material; 58 59 public List<Renderer> FoundInRenderers=new List<Renderer>(); 60 public List<Graphic> FoundInGraphics=new List<Graphic>(); 61 public bool instance; 62 public bool isgui; 63 public bool isSky; 64 65 public MaterialDetails() 66 { 67 instance = false; 68 isgui = false; 69 isSky = false; 70 } 71 }; 72 73 public class MeshDetails 74 { 75 76 public Mesh mesh; 77 78 public List<MeshFilter> FoundInMeshFilters=new List<MeshFilter>(); 79 public List<SkinnedMeshRenderer> FoundInSkinnedMeshRenderer=new List<SkinnedMeshRenderer>(); 80 public bool instance; 81 82 public MeshDetails() 83 { 84 instance = false; 85 } 86 }; 87 88 public class MissingGraphic{ 89 public Transform Object; 90 public string type; 91 public string name; 92 } 93 94 public class ResourceChecker : EditorWindow { 95 96 97 string[] inspectToolbarStrings = { "Textures", "Materials","Meshes"}; 98 string[] inspectToolbarStrings2 = { "Textures", "Materials","Meshes", "Missing"}; 99 100 enum InspectType 101 { 102 Textures,Materials,Meshes,Missing 103 }; 104 105 bool IncludeDisabledObjects=true; 106 bool IncludeSpriteAnimations=true; 107 bool IncludeScriptReferences=true; 108 bool IncludeGuiElements=true; 109 bool thingsMissing = false; 110 111 InspectType ActiveInspectType=InspectType.Textures; 112 113 float ThumbnailWidth=40; 114 float ThumbnailHeight=40; 115 116 List<TextureDetails> ActiveTextures=new List<TextureDetails>(); 117 List<MaterialDetails> ActiveMaterials=new List<MaterialDetails>(); 118 List<MeshDetails> ActiveMeshDetails=new List<MeshDetails>(); 119 List<MissingGraphic> MissingObjects = new List<MissingGraphic> (); 120 121 Vector2 textureListScrollPos=new Vector2(0,0); 122 Vector2 materialListScrollPos=new Vector2(0,0); 123 Vector2 meshListScrollPos=new Vector2(0,0); 124 Vector2 missingListScrollPos = new Vector2 (0,0); 125 126 int TotalTextureMemory=0; 127 int TotalMeshVertices=0; 128 129 bool ctrlPressed=false; 130 131 static int MinWidth=475; 132 Color defColor; 133 134 bool collectedInPlayingMode; 135 136 [MenuItem ("Window/Resource Checker")] 137 static void Init () 138 { 139 ResourceChecker window = (ResourceChecker) EditorWindow.GetWindow (typeof (ResourceChecker)); 140 window.CheckResources(); 141 window.minSize=new Vector2(MinWidth,475); 142 } 143 144 void OnGUI () 145 { 146 defColor = GUI.color; 147 IncludeDisabledObjects = GUILayout.Toggle(IncludeDisabledObjects, "Include disabled objects", GUILayout.Width(300)); 148 IncludeSpriteAnimations = GUILayout.Toggle(IncludeSpriteAnimations, "Look in sprite animations", GUILayout.Width(300)); 149 GUI.color = new Color (0.8f, 0.8f, 1.0f, 1.0f); 150 IncludeScriptReferences = GUILayout.Toggle(IncludeScriptReferences, "Look in behavior fields", GUILayout.Width(300)); 151 GUI.color = new Color (1.0f, 0.95f, 0.8f, 1.0f); 152 IncludeGuiElements = GUILayout.Toggle(IncludeGuiElements, "Look in GUI elements", GUILayout.Width(300)); 153 GUI.color = defColor; 154 GUILayout.BeginArea(new Rect(position.width-85,5,100,65)); 155 if (GUILayout.Button("Calculate",GUILayout.Width(80), GUILayout.Height(40))) 156 CheckResources(); 157 if (GUILayout.Button("CleanUp",GUILayout.Width(80), GUILayout.Height(20))) 158 Resources.UnloadUnusedAssets(); 159 GUILayout.EndArea(); 160 RemoveDestroyedResources(); 161 162 GUILayout.Space(30); 163 if (thingsMissing == true) { 164 EditorGUI.HelpBox (new Rect(8,75,300,25),"Some GameObjects are missing graphical elements.", MessageType.Error); 165 } 166 GUILayout.BeginHorizontal(); 167 GUILayout.Label("Textures "+ActiveTextures.Count+" - "+FormatSizeString(TotalTextureMemory)); 168 GUILayout.Label("Materials "+ActiveMaterials.Count); 169 GUILayout.Label("Meshes "+ActiveMeshDetails.Count+" - "+TotalMeshVertices+" verts"); 170 GUILayout.EndHorizontal(); 171 if (thingsMissing == true) { 172 ActiveInspectType = (InspectType)GUILayout.Toolbar ((int)ActiveInspectType, inspectToolbarStrings2); 173 } else { 174 ActiveInspectType = (InspectType)GUILayout.Toolbar ((int)ActiveInspectType, inspectToolbarStrings); 175 } 176 177 ctrlPressed=Event.current.control || Event.current.command; 178 179 switch (ActiveInspectType) 180 { 181 case InspectType.Textures: 182 ListTextures(); 183 break; 184 case InspectType.Materials: 185 ListMaterials(); 186 break; 187 case InspectType.Meshes: 188 ListMeshes(); 189 break; 190 case InspectType.Missing: 191 ListMissing(); 192 break; 193 } 194 } 195 196 private void RemoveDestroyedResources() 197 { 198 if (collectedInPlayingMode != Application.isPlaying) 199 { 200 ActiveTextures.Clear(); 201 ActiveMaterials.Clear(); 202 ActiveMeshDetails.Clear(); 203 MissingObjects.Clear (); 204 thingsMissing = false; 205 collectedInPlayingMode = Application.isPlaying; 206 } 207 208 ActiveTextures.RemoveAll(x => !x.texture); 209 ActiveTextures.ForEach(delegate(TextureDetails obj) { 210 obj.FoundInAnimators.RemoveAll(x => !x); 211 obj.FoundInMaterials.RemoveAll(x => !x); 212 obj.FoundInRenderers.RemoveAll(x => !x); 213 obj.FoundInScripts.RemoveAll(x => !x); 214 obj.FoundInGraphics.RemoveAll(x => !x); 215 }); 216 217 ActiveMaterials.RemoveAll(x => !x.material); 218 ActiveMaterials.ForEach(delegate(MaterialDetails obj) { 219 obj.FoundInRenderers.RemoveAll(x => !x); 220 obj.FoundInGraphics.RemoveAll(x => !x); 221 }); 222 223 ActiveMeshDetails.RemoveAll(x => !x.mesh); 224 ActiveMeshDetails.ForEach(delegate(MeshDetails obj) { 225 obj.FoundInMeshFilters.RemoveAll(x => !x); 226 obj.FoundInSkinnedMeshRenderer.RemoveAll(x => !x); 227 }); 228 229 TotalTextureMemory = 0; 230 foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB; 231 232 TotalMeshVertices = 0; 233 foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount; 234 } 235 236 int GetBitsPerPixel(TextureFormat format) 237 { 238 switch (format) 239 { 240 case TextureFormat.Alpha8: // Alpha-only texture format. 241 return 8; 242 case TextureFormat.ARGB4444: // A 16 bits/pixel texture format. Texture stores color with an alpha channel. 243 return 16; 244 case TextureFormat.RGBA4444: // A 16 bits/pixel texture format. 245 return 16; 246 case TextureFormat.RGB24: // A color texture format. 247 return 24; 248 case TextureFormat.RGBA32: //Color with an alpha channel texture format. 249 return 32; 250 case TextureFormat.ARGB32: //Color with an alpha channel texture format. 251 return 32; 252 case TextureFormat.RGB565: // A 16 bit color texture format. 253 return 16; 254 case TextureFormat.DXT1: // Compressed color texture format. 255 return 4; 256 case TextureFormat.DXT5: // Compressed color with alpha channel texture format. 257 return 8; 258 /* 259 case TextureFormat.WiiI4: // Wii texture format. 260 case TextureFormat.WiiI8: // Wii texture format. Intensity 8 bit. 261 case TextureFormat.WiiIA4: // Wii texture format. Intensity + Alpha 8 bit (4 + 4). 262 case TextureFormat.WiiIA8: // Wii texture format. Intensity + Alpha 16 bit (8 + 8). 263 case TextureFormat.WiiRGB565: // Wii texture format. RGB 16 bit (565). 264 case TextureFormat.WiiRGB5A3: // Wii texture format. RGBA 16 bit (4443). 265 case TextureFormat.WiiRGBA8: // Wii texture format. RGBA 32 bit (8888). 266 case TextureFormat.WiiCMPR: // Compressed Wii texture format. 4 bits/texel, ~RGB8A1 (Outline alpha is not currently supported). 267 return 0; //Not supported yet 268 */ 269 case TextureFormat.PVRTC_RGB2:// PowerVR (iOS) 2 bits/pixel compressed color texture format. 270 return 2; 271 case TextureFormat.PVRTC_RGBA2:// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format 272 return 2; 273 case TextureFormat.PVRTC_RGB4:// PowerVR (iOS) 4 bits/pixel compressed color texture format. 274 return 4; 275 case TextureFormat.PVRTC_RGBA4:// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format 276 return 4; 277 case TextureFormat.ETC_RGB4:// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format. 278 return 4; 279 case TextureFormat.ATC_RGB4:// ATC (ATITC) 4 bits/pixel compressed RGB texture format. 280 return 4; 281 case TextureFormat.ATC_RGBA8:// ATC (ATITC) 8 bits/pixel compressed RGB texture format. 282 return 8; 283 case TextureFormat.BGRA32:// Format returned by iPhone camera 284 return 32; 285 #if !UNITY_5 && !UNITY_5_3_OR_NEWER 286 case TextureFormat.ATF_RGB_DXT1:// Flash-specific RGB DXT1 compressed color texture format. 287 case TextureFormat.ATF_RGBA_JPG:// Flash-specific RGBA JPG-compressed color texture format. 288 case TextureFormat.ATF_RGB_JPG:// Flash-specific RGB JPG-compressed color texture format. 289 return 0; //Not supported yet 290 #endif 291 } 292 return 0; 293 } 294 295 int CalculateTextureSizeBytes(Texture tTexture) 296 { 297 298 int tWidth=tTexture.width; 299 int tHeight=tTexture.height; 300 if (tTexture is Texture2D) 301 { 302 Texture2D tTex2D=tTexture as Texture2D; 303 int bitsPerPixel=GetBitsPerPixel(tTex2D.format); 304 int mipMapCount=tTex2D.mipmapCount; 305 int mipLevel=1; 306 int tSize=0; 307 while (mipLevel<=mipMapCount) 308 { 309 tSize+=tWidth*tHeight*bitsPerPixel/8; 310 tWidth=tWidth/2; 311 tHeight=tHeight/2; 312 mipLevel++; 313 } 314 return tSize; 315 } 316 if (