├── README └── ResourceChecker.cs /README: -------------------------------------------------------------------------------- 1 | // Unity Resource Checker 2 | // (c) 2012 Simon Oliver / HandCircus / hello@handcircus.com 3 | // https://github.com/handcircus/Unity-Resource-Checker 4 | // Public domain, do with whatever you like, commercial or not 5 | // This comes with no warranty, use at your own risk! 6 | 7 | Resource checker is designed to help bring visibility to resource use in your scenes (ie what assets are using up memory, 8 | which meshes are a bit too detailed, where are my materials and textures being used). 9 | 10 | It should also be useful to check for redundant materials, textures you forget you're using, textures that can be compressed or reduced in size. 11 | 12 | To use, just create an "Editor" folder within "Assets" in your project if you don't already have one, and drop ResourceChecker.cs in there. 13 | 14 | In Unity you'll see a new option under "Window" -> "Resource Checker" 15 | 16 | To use, once the window is open, just click 'Refresh' and it will list all active textures, materials and meshes in the scene 17 | 18 | Textures 19 | -------- 20 | 21 | - Textures are listed in descending memory size 22 | - Click the texture name to open the asset in the project window 23 | - The size of the texture, compression type and dimensions are show 24 | - Click the 'X Mat' button to select all materials that use this texture in the scene 25 | - Click the 'X GO' to select all game objects in the scene that use this texture 26 | 27 | Materials 28 | --------- 29 | 30 | - Click the material name to open the material asset in the project window 31 | - Click the 'X GO' to select all game objects in the scene that use this material 32 | 33 | Meshes 34 | ------ 35 | - Meshes are listed in descending vertex count 36 | - Click the mesh name to open the mesh in the project window 37 | - Click the 'X GO' to select all game objects in the scene that use this mesh 38 | 39 | Its probably got a bunch of bugs and weird issues - feel free to help improve, fix up! 40 | -------------------------------------------------------------------------------- /ResourceChecker.cs: -------------------------------------------------------------------------------- 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 18 | { 19 | public bool isCubeMap; 20 | public int memSizeKB; 21 | public Texture texture; 22 | public TextureFormat format; 23 | public int mipMapCount; 24 | public List FoundInMaterials=new List(); 25 | public List FoundInRenderers=new List(); 26 | public List FoundInAnimators = new List(); 27 | public List FoundInScripts = new List(); 28 | public List FoundInGraphics = new List(); 29 | public List FoundInButtons = new List(); 30 | public bool isSky; 31 | public bool instance; 32 | public bool isgui; 33 | public TextureDetails() 34 | { 35 | 36 | } 37 | 38 | public bool Equals(TextureDetails other) 39 | { 40 | return texture != null && other.texture != null && 41 | texture.GetNativeTexturePtr() == other.texture.GetNativeTexturePtr(); 42 | } 43 | 44 | public override int GetHashCode() 45 | { 46 | return (int)texture.GetNativeTexturePtr(); 47 | } 48 | 49 | public override bool Equals(object obj) 50 | { 51 | return Equals(obj as TextureDetails); 52 | } 53 | }; 54 | 55 | public class MaterialDetails 56 | { 57 | 58 | public Material material; 59 | 60 | public List FoundInRenderers=new List(); 61 | public List FoundInGraphics=new List(); 62 | public bool instance; 63 | public bool isgui; 64 | public bool isSky; 65 | 66 | public MaterialDetails() 67 | { 68 | instance = false; 69 | isgui = false; 70 | isSky = false; 71 | } 72 | }; 73 | 74 | public class MeshDetails 75 | { 76 | 77 | public Mesh mesh; 78 | 79 | public List FoundInMeshFilters=new List(); 80 | public List FoundInSkinnedMeshRenderer=new List(); 81 | public List StaticBatchingEnabled =new List(); 82 | public bool instance; 83 | 84 | public MeshDetails() 85 | { 86 | instance = false; 87 | } 88 | }; 89 | 90 | public class MissingGraphic{ 91 | public Transform Object; 92 | public string type; 93 | public string name; 94 | } 95 | 96 | public class ResourceChecker : EditorWindow { 97 | 98 | 99 | string[] inspectToolbarStrings = {"Textures", "Materials","Meshes"}; 100 | string[] inspectToolbarStrings2 = {"Textures", "Materials","Meshes", "Missing"}; 101 | 102 | enum InspectType 103 | { 104 | Textures,Materials,Meshes,Missing 105 | }; 106 | 107 | bool IncludeDisabledObjects=true; 108 | bool IncludeSpriteAnimations=true; 109 | bool IncludeScriptReferences=true; 110 | bool IncludeGuiElements=true; 111 | bool IncludeLightmapTextures=true; 112 | bool thingsMissing = false; 113 | 114 | InspectType ActiveInspectType=InspectType.Textures; 115 | 116 | float ThumbnailWidth=40; 117 | float ThumbnailHeight=40; 118 | 119 | List ActiveTextures=new List(); 120 | List ActiveMaterials=new List(); 121 | List ActiveMeshDetails=new List(); 122 | List MissingObjects = new List (); 123 | 124 | Vector2 textureListScrollPos=new Vector2(0,0); 125 | Vector2 materialListScrollPos=new Vector2(0,0); 126 | Vector2 meshListScrollPos=new Vector2(0,0); 127 | Vector2 missingListScrollPos = new Vector2 (0,0); 128 | 129 | int TotalTextureMemory=0; 130 | int TotalMeshVertices=0; 131 | 132 | bool ctrlPressed=false; 133 | 134 | static int MinWidth=475; 135 | Color defColor; 136 | 137 | bool collectedInPlayingMode; 138 | 139 | [MenuItem ("Window/Resource Checker")] 140 | static void Init () 141 | { 142 | ResourceChecker window = (ResourceChecker) EditorWindow.GetWindow (typeof (ResourceChecker)); 143 | window.CheckResources(); 144 | window.minSize=new Vector2(MinWidth,475); 145 | } 146 | 147 | void OnGUI () 148 | { 149 | defColor = GUI.color; 150 | IncludeDisabledObjects = GUILayout.Toggle(IncludeDisabledObjects, "Include disabled objects", GUILayout.Width(300)); 151 | IncludeSpriteAnimations = GUILayout.Toggle(IncludeSpriteAnimations, "Look in sprite animations", GUILayout.Width(300)); 152 | GUI.color = new Color (0.8f, 0.8f, 1.0f, 1.0f); 153 | IncludeScriptReferences = GUILayout.Toggle(IncludeScriptReferences, "Look in behavior fields", GUILayout.Width(300)); 154 | GUI.color = new Color (1.0f, 0.95f, 0.8f, 1.0f); 155 | IncludeGuiElements = GUILayout.Toggle(IncludeGuiElements, "Look in GUI elements", GUILayout.Width(300)); 156 | IncludeLightmapTextures = GUILayout.Toggle(IncludeLightmapTextures, "Look in Lightmap textures", GUILayout.Width(300)); 157 | GUI.color = defColor; 158 | GUILayout.BeginArea(new Rect(position.width-85,5,100,65)); 159 | if (GUILayout.Button("Calculate",GUILayout.Width(80), GUILayout.Height(40))) 160 | CheckResources(); 161 | if (GUILayout.Button("CleanUp",GUILayout.Width(80), GUILayout.Height(20))) 162 | Resources.UnloadUnusedAssets(); 163 | GUILayout.EndArea(); 164 | RemoveDestroyedResources(); 165 | 166 | GUILayout.Space(30); 167 | if (thingsMissing == true) { 168 | EditorGUI.HelpBox (new Rect(8,93,300,25),"Some GameObjects are missing graphical elements.", MessageType.Error); 169 | } 170 | GUILayout.BeginHorizontal(); 171 | GUILayout.Label("Textures "+ActiveTextures.Count+" - "+FormatSizeString(TotalTextureMemory)); 172 | GUILayout.Label("Materials "+ActiveMaterials.Count); 173 | GUILayout.Label("Meshes "+ActiveMeshDetails.Count+" - "+TotalMeshVertices+" verts"); 174 | GUILayout.EndHorizontal(); 175 | if (thingsMissing == true) { 176 | ActiveInspectType = (InspectType)GUILayout.Toolbar ((int)ActiveInspectType, inspectToolbarStrings2); 177 | } else { 178 | ActiveInspectType = (InspectType)GUILayout.Toolbar ((int)ActiveInspectType, inspectToolbarStrings); 179 | } 180 | 181 | ctrlPressed=Event.current.control || Event.current.command; 182 | 183 | switch (ActiveInspectType) 184 | { 185 | case InspectType.Textures: 186 | ListTextures(); 187 | break; 188 | case InspectType.Materials: 189 | ListMaterials(); 190 | break; 191 | case InspectType.Meshes: 192 | ListMeshes(); 193 | break; 194 | case InspectType.Missing: 195 | ListMissing(); 196 | break; 197 | } 198 | } 199 | 200 | private void RemoveDestroyedResources() 201 | { 202 | if (collectedInPlayingMode != Application.isPlaying) 203 | { 204 | ActiveTextures.Clear(); 205 | ActiveMaterials.Clear(); 206 | ActiveMeshDetails.Clear(); 207 | MissingObjects.Clear (); 208 | thingsMissing = false; 209 | collectedInPlayingMode = Application.isPlaying; 210 | } 211 | 212 | ActiveTextures.RemoveAll(x => !x.texture); 213 | ActiveTextures.ForEach(delegate(TextureDetails obj) { 214 | obj.FoundInAnimators.RemoveAll(x => !x); 215 | obj.FoundInMaterials.RemoveAll(x => !x); 216 | obj.FoundInRenderers.RemoveAll(x => !x); 217 | obj.FoundInScripts.RemoveAll(x => !x); 218 | obj.FoundInGraphics.RemoveAll(x => !x); 219 | }); 220 | 221 | ActiveMaterials.RemoveAll(x => !x.material); 222 | ActiveMaterials.ForEach(delegate(MaterialDetails obj) { 223 | obj.FoundInRenderers.RemoveAll(x => !x); 224 | obj.FoundInGraphics.RemoveAll(x => !x); 225 | }); 226 | 227 | ActiveMeshDetails.RemoveAll(x => !x.mesh); 228 | ActiveMeshDetails.ForEach(delegate(MeshDetails obj) { 229 | obj.FoundInMeshFilters.RemoveAll(x => !x); 230 | obj.FoundInSkinnedMeshRenderer.RemoveAll(x => !x); 231 | obj.StaticBatchingEnabled.RemoveAll(x => !x); 232 | }); 233 | 234 | TotalTextureMemory = 0; 235 | foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB; 236 | 237 | TotalMeshVertices = 0; 238 | foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount; 239 | } 240 | 241 | int GetBitsPerPixel(TextureFormat format) 242 | { 243 | switch (format) 244 | { 245 | case TextureFormat.Alpha8: // Alpha-only texture format. 246 | return 8; 247 | case TextureFormat.ARGB4444: // A 16 bits/pixel texture format. Texture stores color with an alpha channel. 248 | return 16; 249 | case TextureFormat.RGBA4444: // A 16 bits/pixel texture format. 250 | return 16; 251 | case TextureFormat.RGB24: // A color texture format. 252 | return 24; 253 | case TextureFormat.RGBA32: //Color with an alpha channel texture format. 254 | return 32; 255 | case TextureFormat.ARGB32: //Color with an alpha channel texture format. 256 | return 32; 257 | case TextureFormat.RGB565: // A 16 bit color texture format. 258 | return 16; 259 | case TextureFormat.DXT1: // Compressed color texture format. 260 | return 4; 261 | case TextureFormat.DXT5: // Compressed color with alpha channel texture format. 262 | return 8; 263 | /* 264 | case TextureFormat.WiiI4: // Wii texture format. 265 | case TextureFormat.WiiI8: // Wii texture format. Intensity 8 bit. 266 | case TextureFormat.WiiIA4: // Wii texture format. Intensity + Alpha 8 bit (4 + 4). 267 | case TextureFormat.WiiIA8: // Wii texture format. Intensity + Alpha 16 bit (8 + 8). 268 | case TextureFormat.WiiRGB565: // Wii texture format. RGB 16 bit (565). 269 | case TextureFormat.WiiRGB5A3: // Wii texture format. RGBA 16 bit (4443). 270 | case TextureFormat.WiiRGBA8: // Wii texture format. RGBA 32 bit (8888). 271 | case TextureFormat.WiiCMPR: // Compressed Wii texture format. 4 bits/texel, ~RGB8A1 (Outline alpha is not currently supported). 272 | return 0; //Not supported yet 273 | */ 274 | case TextureFormat.PVRTC_RGB2:// PowerVR (iOS) 2 bits/pixel compressed color texture format. 275 | return 2; 276 | case TextureFormat.PVRTC_RGBA2:// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format 277 | return 2; 278 | case TextureFormat.PVRTC_RGB4:// PowerVR (iOS) 4 bits/pixel compressed color texture format. 279 | return 4; 280 | case TextureFormat.PVRTC_RGBA4:// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format 281 | return 4; 282 | case TextureFormat.ETC_RGB4:// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format. 283 | return 4; 284 | case TextureFormat.ETC2_RGBA8: 285 | return 8; 286 | case TextureFormat.EAC_R: 287 | return 4; 288 | case TextureFormat.BGRA32:// Format returned by iPhone camera 289 | return 32; 290 | } 291 | return 0; 292 | } 293 | 294 | int CalculateTextureSizeBytes(Texture tTexture) 295 | { 296 | 297 | int tWidth=tTexture.width; 298 | int tHeight=tTexture.height; 299 | if (tTexture is Texture2D) 300 | { 301 | Texture2D tTex2D=tTexture as Texture2D; 302 | int bitsPerPixel=GetBitsPerPixel(tTex2D.format); 303 | int mipMapCount=tTex2D.mipmapCount; 304 | int mipLevel=1; 305 | int tSize=0; 306 | while (mipLevel<=mipMapCount) 307 | { 308 | tSize+=tWidth*tHeight*bitsPerPixel/8; 309 | tWidth=tWidth/2; 310 | tHeight=tHeight/2; 311 | mipLevel++; 312 | } 313 | return tSize; 314 | } 315 | if (tTexture is Texture2DArray) 316 | { 317 | Texture2DArray tTex2D=tTexture as Texture2DArray; 318 | int bitsPerPixel=GetBitsPerPixel(tTex2D.format); 319 | int mipMapCount=10; 320 | int mipLevel=1; 321 | int tSize=0; 322 | while (mipLevel<=mipMapCount) 323 | { 324 | tSize+=tWidth*tHeight*bitsPerPixel/8; 325 | tWidth=tWidth/2; 326 | tHeight=tHeight/2; 327 | mipLevel++; 328 | } 329 | return tSize*((Texture2DArray)tTex2D).depth; 330 | } 331 | if (tTexture is Cubemap) { 332 | Cubemap tCubemap = tTexture as Cubemap; 333 | int bitsPerPixel = GetBitsPerPixel (tCubemap.format); 334 | return tWidth * tHeight * 6 * bitsPerPixel / 8; 335 | } 336 | return 0; 337 | } 338 | 339 | 340 | void SelectObject(Object selectedObject,bool append) 341 | { 342 | if (append) 343 | { 344 | List currentSelection=new List(Selection.objects); 345 | // Allow toggle selection 346 | if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject); 347 | else currentSelection.Add(selectedObject); 348 | 349 | Selection.objects=currentSelection.ToArray(); 350 | } 351 | else Selection.activeObject=selectedObject; 352 | } 353 | 354 | void SelectObjects(List selectedObjects,bool append) 355 | { 356 | if (append) 357 | { 358 | List currentSelection=new List(Selection.objects); 359 | currentSelection.AddRange(selectedObjects); 360 | Selection.objects=currentSelection.ToArray(); 361 | } 362 | else Selection.objects=selectedObjects.ToArray(); 363 | } 364 | 365 | void ListTextures() 366 | { 367 | textureListScrollPos = EditorGUILayout.BeginScrollView(textureListScrollPos); 368 | 369 | foreach (TextureDetails tDetails in ActiveTextures) 370 | { 371 | 372 | GUILayout.BeginHorizontal (); 373 | Texture tex =tDetails.texture; 374 | if(tDetails.texture.GetType() == typeof(Texture2DArray) || tDetails.texture.GetType() == typeof(Cubemap)){ 375 | tex = AssetPreview.GetMiniThumbnail(tDetails.texture); 376 | } 377 | GUILayout.Box(tex, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight)); 378 | 379 | if (tDetails.instance == true) 380 | GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f); 381 | if (tDetails.isgui == true) 382 | GUI.color = new Color (defColor.r, 0.95f, 0.8f, 1.0f); 383 | if (tDetails.isSky) 384 | GUI.color = new Color (0.9f, defColor.g, defColor.b, 1.0f); 385 | if(GUILayout.Button(tDetails.texture.name,GUILayout.Width(150))) 386 | { 387 | SelectObject(tDetails.texture,ctrlPressed); 388 | } 389 | GUI.color = defColor; 390 | 391 | string sizeLabel=""+tDetails.texture.width+"x"+tDetails.texture.height; 392 | if (tDetails.isCubeMap) sizeLabel+="x6"; 393 | if (tDetails.texture.GetType () == typeof(Texture2DArray)) 394 | sizeLabel+= "[]\n" + ((Texture2DArray)tDetails.texture).depth+"depths"; 395 | sizeLabel+=" - "+tDetails.mipMapCount+"mip\n"+FormatSizeString(tDetails.memSizeKB)+" - "+tDetails.format; 396 | 397 | GUILayout.Label (sizeLabel,GUILayout.Width(120)); 398 | 399 | if(GUILayout.Button(tDetails.FoundInMaterials.Count+" Mat",GUILayout.Width(50))) 400 | { 401 | SelectObjects(tDetails.FoundInMaterials,ctrlPressed); 402 | } 403 | 404 | HashSet FoundObjects = new HashSet(); 405 | foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject); 406 | foreach (Animator animator in tDetails.FoundInAnimators) FoundObjects.Add(animator.gameObject); 407 | foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject); 408 | foreach (Button button in tDetails.FoundInButtons) FoundObjects.Add(button.gameObject); 409 | foreach (MonoBehaviour script in tDetails.FoundInScripts) FoundObjects.Add(script.gameObject); 410 | if (GUILayout.Button(FoundObjects.Count+" GO",GUILayout.Width(50))) 411 | { 412 | SelectObjects(new List(FoundObjects),ctrlPressed); 413 | } 414 | 415 | GUILayout.EndHorizontal(); 416 | } 417 | if (ActiveTextures.Count>0) 418 | { 419 | EditorGUILayout.Space(); 420 | GUILayout.BeginHorizontal (); 421 | //GUILayout.Box(" ",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight)); 422 | if(GUILayout.Button("Select \n All",GUILayout.Width(ThumbnailWidth*2))) 423 | { 424 | List AllTextures=new List(); 425 | foreach (TextureDetails tDetails in ActiveTextures) AllTextures.Add(tDetails.texture); 426 | SelectObjects(AllTextures,ctrlPressed); 427 | } 428 | EditorGUILayout.EndHorizontal(); 429 | } 430 | EditorGUILayout.EndScrollView(); 431 | } 432 | 433 | void ListMaterials() 434 | { 435 | materialListScrollPos = EditorGUILayout.BeginScrollView(materialListScrollPos); 436 | 437 | foreach (MaterialDetails tDetails in ActiveMaterials) 438 | { 439 | if (tDetails.material!=null) 440 | { 441 | GUILayout.BeginHorizontal (); 442 | 443 | GUILayout.Box(AssetPreview.GetAssetPreview(tDetails.material), GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight)); 444 | 445 | if (tDetails.instance == true) 446 | GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f); 447 | if (tDetails.isgui == true) 448 | GUI.color = new Color (defColor.r, 0.95f, 0.8f, 1.0f); 449 | if (tDetails.isSky) 450 | GUI.color = new Color (0.9f, defColor.g, defColor.b, 1.0f); 451 | if(GUILayout.Button(tDetails.material.name,GUILayout.Width(150))) 452 | { 453 | SelectObject(tDetails.material,ctrlPressed); 454 | } 455 | GUI.color = defColor; 456 | 457 | string shaderLabel = tDetails.material.shader != null ? tDetails.material.shader.name : "no shader"; 458 | GUILayout.Label (shaderLabel, GUILayout.Width(200)); 459 | 460 | if(GUILayout.Button((tDetails.FoundInRenderers.Count + tDetails.FoundInGraphics.Count) +" GO",GUILayout.Width(50))) 461 | { 462 | List FoundObjects=new List(); 463 | foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject); 464 | foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject); 465 | SelectObjects(FoundObjects,ctrlPressed); 466 | } 467 | 468 | var queue = tDetails.material.renderQueue; 469 | EditorGUI.BeginChangeCheck(); 470 | queue = EditorGUILayout.DelayedIntField(queue, GUILayout.Width(35)); 471 | if (EditorGUI.EndChangeCheck()) 472 | { 473 | tDetails.material.renderQueue = queue; 474 | ActiveMaterials.Sort(MaterialSorter); 475 | GUIUtility.ExitGUI(); 476 | break; 477 | } 478 | 479 | GUILayout.EndHorizontal(); 480 | } 481 | } 482 | EditorGUILayout.EndScrollView(); 483 | } 484 | 485 | /// 486 | /// Sort by RenderQueue 487 | /// 488 | static int MaterialSorter(MaterialDetails first, MaterialDetails second) 489 | { 490 | var firstIsNull = first.material == null; 491 | var secondIsNull = second.material == null; 492 | 493 | if (firstIsNull && secondIsNull) return 0; 494 | if (firstIsNull) return int.MaxValue; 495 | if (secondIsNull) return int.MinValue; 496 | 497 | return first.material.renderQueue - second.material.renderQueue; 498 | } 499 | 500 | void ListMeshes() 501 | { 502 | meshListScrollPos = EditorGUILayout.BeginScrollView(meshListScrollPos); 503 | 504 | foreach (MeshDetails tDetails in ActiveMeshDetails) 505 | { 506 | if (tDetails.mesh!=null) 507 | { 508 | GUILayout.BeginHorizontal (); 509 | string name = tDetails.mesh.name; 510 | if (name == null || name.Count() < 1) 511 | name = tDetails.FoundInMeshFilters[0].gameObject.name; 512 | if (tDetails.instance == true) 513 | GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f); 514 | if(GUILayout.Button(name,GUILayout.Width(150))) 515 | { 516 | SelectObject(tDetails.mesh,ctrlPressed); 517 | } 518 | GUI.color = defColor; 519 | string sizeLabel=""+tDetails.mesh.vertexCount+" vert"; 520 | 521 | GUILayout.Label (sizeLabel,GUILayout.Width(100)); 522 | 523 | 524 | if(GUILayout.Button(tDetails.FoundInMeshFilters.Count + " GO",GUILayout.Width(50))) 525 | { 526 | List FoundObjects=new List(); 527 | foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters) FoundObjects.Add(meshFilter.gameObject); 528 | SelectObjects(FoundObjects,ctrlPressed); 529 | } 530 | if (tDetails.FoundInSkinnedMeshRenderer.Count > 0) { 531 | if (GUILayout.Button (tDetails.FoundInSkinnedMeshRenderer.Count + " skinned mesh GO", GUILayout.Width (140))) { 532 | List FoundObjects = new List (); 533 | foreach (SkinnedMeshRenderer skinnedMeshRenderer in tDetails.FoundInSkinnedMeshRenderer) 534 | FoundObjects.Add (skinnedMeshRenderer.gameObject); 535 | SelectObjects (FoundObjects, ctrlPressed); 536 | } 537 | } else { 538 | GUI.color = new Color (defColor.r, defColor.g, defColor.b, 0.5f); 539 | GUILayout.Label(" 0 skinned mesh"); 540 | GUI.color = defColor; 541 | } 542 | 543 | if (tDetails.StaticBatchingEnabled.Count > 0) { 544 | if (GUILayout.Button (tDetails.StaticBatchingEnabled.Count + " Static Batching", GUILayout.Width (140))) { 545 | List FoundObjects = new List (); 546 | foreach (var obj in tDetails.StaticBatchingEnabled) 547 | FoundObjects.Add (obj); 548 | SelectObjects (FoundObjects, ctrlPressed); 549 | } 550 | } else { 551 | GUI.color = new Color (defColor.r, defColor.g, defColor.b, 0.5f); 552 | GUILayout.Label(" 0 static batching"); 553 | GUI.color = defColor; 554 | } 555 | 556 | 557 | GUILayout.EndHorizontal(); 558 | } 559 | } 560 | EditorGUILayout.EndScrollView(); 561 | } 562 | 563 | void ListMissing(){ 564 | missingListScrollPos = EditorGUILayout.BeginScrollView(missingListScrollPos); 565 | foreach (MissingGraphic dMissing in MissingObjects) { 566 | GUILayout.BeginHorizontal (); 567 | if (GUILayout.Button (dMissing.name, GUILayout.Width (150))) 568 | SelectObject (dMissing.Object, ctrlPressed); 569 | GUILayout.Label ("missing ", GUILayout.Width(48)); 570 | switch (dMissing.type) { 571 | case "mesh": 572 | GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f); 573 | break; 574 | case "sprite": 575 | GUI.color = new Color (defColor.r, 0.8f, 0.8f, 1.0f); 576 | break; 577 | case "material": 578 | GUI.color = new Color (0.8f, defColor.g, 0.8f, 1.0f); 579 | break; 580 | } 581 | GUILayout.Label (dMissing.type); 582 | GUI.color = defColor; 583 | GUILayout.EndHorizontal (); 584 | } 585 | EditorGUILayout.EndScrollView(); 586 | } 587 | 588 | string FormatSizeString(int memSizeKB) 589 | { 590 | if (memSizeKB<1024) return ""+memSizeKB+"k"; 591 | else 592 | { 593 | float memSizeMB=((float)memSizeKB)/1024.0f; 594 | return memSizeMB.ToString("0.00")+"Mb"; 595 | } 596 | } 597 | 598 | 599 | TextureDetails FindTextureDetails(Texture tTexture) 600 | { 601 | foreach (TextureDetails tTextureDetails in ActiveTextures) 602 | { 603 | if (tTextureDetails.texture==tTexture) return tTextureDetails; 604 | } 605 | return null; 606 | 607 | } 608 | 609 | MaterialDetails FindMaterialDetails(Material tMaterial) 610 | { 611 | foreach (MaterialDetails tMaterialDetails in ActiveMaterials) 612 | { 613 | if (tMaterialDetails.material==tMaterial) return tMaterialDetails; 614 | } 615 | return null; 616 | 617 | } 618 | 619 | MeshDetails FindMeshDetails(Mesh tMesh) 620 | { 621 | foreach (MeshDetails tMeshDetails in ActiveMeshDetails) 622 | { 623 | if (tMeshDetails.mesh==tMesh) return tMeshDetails; 624 | } 625 | return null; 626 | 627 | } 628 | 629 | 630 | void CheckResources() 631 | { 632 | ActiveTextures.Clear(); 633 | ActiveMaterials.Clear(); 634 | ActiveMeshDetails.Clear(); 635 | MissingObjects.Clear (); 636 | thingsMissing = false; 637 | 638 | Renderer[] renderers = FindObjects(); 639 | 640 | MaterialDetails skyMat = new MaterialDetails (); 641 | skyMat.material = RenderSettings.skybox; 642 | skyMat.isSky = true; 643 | ActiveMaterials.Add (skyMat); 644 | 645 | //Debug.Log("Total renderers "+renderers.Length); 646 | foreach (Renderer renderer in renderers) 647 | { 648 | //Debug.Log("Renderer is "+renderer.name); 649 | foreach (Material material in renderer.sharedMaterials) 650 | { 651 | 652 | MaterialDetails tMaterialDetails = FindMaterialDetails(material); 653 | if (tMaterialDetails == null) 654 | { 655 | tMaterialDetails = new MaterialDetails(); 656 | tMaterialDetails.material = material; 657 | ActiveMaterials.Add(tMaterialDetails); 658 | } 659 | tMaterialDetails.FoundInRenderers.Add(renderer); 660 | } 661 | 662 | if (renderer is SpriteRenderer) 663 | { 664 | SpriteRenderer tSpriteRenderer = (SpriteRenderer)renderer; 665 | 666 | if (tSpriteRenderer.sprite != null) { 667 | var tSpriteTextureDetail = GetTextureDetail (tSpriteRenderer.sprite.texture, renderer); 668 | if (!ActiveTextures.Contains (tSpriteTextureDetail)) { 669 | ActiveTextures.Add (tSpriteTextureDetail); 670 | } 671 | } else if (tSpriteRenderer.sprite == null) { 672 | MissingGraphic tMissing = new MissingGraphic (); 673 | tMissing.Object = tSpriteRenderer.transform; 674 | tMissing.type = "sprite"; 675 | tMissing.name = tSpriteRenderer.transform.name; 676 | MissingObjects.Add (tMissing); 677 | thingsMissing = true; 678 | } 679 | } 680 | } 681 | 682 | if (IncludeLightmapTextures) { 683 | LightmapData[] lightmapTextures = LightmapSettings.lightmaps; 684 | 685 | // Unity lightmaps 686 | foreach (LightmapData lightmapData in lightmapTextures) 687 | { 688 | if (lightmapData.lightmapColor != null) 689 | { 690 | var textureDetail = GetTextureDetail (lightmapData.lightmapColor); 691 | 692 | if (!ActiveTextures.Contains (textureDetail)) 693 | ActiveTextures.Add (textureDetail); 694 | } 695 | 696 | if (lightmapData.lightmapDir != null) 697 | { 698 | var textureDetail = GetTextureDetail (lightmapData.lightmapColor); 699 | 700 | if (!ActiveTextures.Contains (textureDetail)) 701 | ActiveTextures.Add (textureDetail); 702 | } 703 | 704 | if (lightmapData.shadowMask != null) 705 | { 706 | var textureDetail = GetTextureDetail (lightmapData.shadowMask); 707 | 708 | if (!ActiveTextures.Contains (textureDetail)) 709 | ActiveTextures.Add (textureDetail); 710 | } 711 | } 712 | } 713 | 714 | if (IncludeGuiElements) 715 | { 716 | Graphic[] graphics = FindObjects(); 717 | 718 | foreach(Graphic graphic in graphics) 719 | { 720 | if (graphic.mainTexture) 721 | { 722 | var tSpriteTextureDetail = GetTextureDetail(graphic.mainTexture, graphic); 723 | if (!ActiveTextures.Contains(tSpriteTextureDetail)) 724 | { 725 | ActiveTextures.Add(tSpriteTextureDetail); 726 | } 727 | } 728 | 729 | if (graphic.materialForRendering) 730 | { 731 | MaterialDetails tMaterialDetails = FindMaterialDetails(graphic.materialForRendering); 732 | if (tMaterialDetails == null) 733 | { 734 | tMaterialDetails = new MaterialDetails(); 735 | tMaterialDetails.material = graphic.materialForRendering; 736 | tMaterialDetails.isgui = true; 737 | ActiveMaterials.Add(tMaterialDetails); 738 | } 739 | tMaterialDetails.FoundInGraphics.Add(graphic); 740 | } 741 | } 742 | 743 | Button[] buttons = FindObjects