with the accumulation of time, the project Assets folder resources will become more and more complex, some texture, material may not have been used, but do not dare to delete.
two plug-ins are Shared here for managing these resources.
p>
A, ResourceChecker
strong> p>
p>
The power of the
plug-in is that it can find all the referenced resources in the current scenario, locate them quickly, and then manually delete any resources that are not located.
p>
code
p>
1 // Resource Checker
2 // (c) 2012 Simon Oliver/HandCircus/[email protected]
3 // (c) 2015 Brice Clocher/Mangatome/[email protected]
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 (tTexture is Texture2DArray)
317 {
318 Texture2DArray tTex2D=tTexture as Texture2DArray;
319 int bitsPerPixel=GetBitsPerPixel(tTex2D.format);
320 int mipMapCount=10;
321 int mipLevel=1;
322 int tSize=0;
323 while (mipLevel<=mipMapCount)
324 {
325 tSize+=tWidth*tHeight*bitsPerPixel/8;
326 tWidth=tWidth/2;
327 tHeight=tHeight/2;
328 mipLevel++;
329 }
330 return tSize*((Texture2DArray)tTex2D).depth;
331 }
332 if (tTexture is Cubemap) {
333 Cubemap tCubemap = tTexture as Cubemap;
334 int bitsPerPixel = GetBitsPerPixel (tCubemap.format);
335 return tWidth * tHeight * 6 * bitsPerPixel/8;
336 }
337 return 0;
338 }
339
340
341 void SelectObject(Object selectedObject,bool append)
342 {
343 if (append)
344 {
345 List<Object> currentSelection=new List<Object>(Selection.objects);
346 // Allow toggle selection
347 if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject);
348 else currentSelection.Add(selectedObject);
349
350 Selection.objects=currentSelection.ToArray();
351 }
352 else Selection.activeObject=selectedObject;
353 }
354
355 void SelectObjects(List<Object> selectedObjects,bool append)
356 {
357 if (append)
358 {
359 List<Object> currentSelection=new List<Object>(Selection.objects);
360 currentSelection.AddRange(selectedObjects);
361 Selection.objects=currentSelection.ToArray();
362 }
363 else Selection.objects=selectedObjects.ToArray();
364 }
365
366 void ListTextures()
367 {
368 textureListScrollPos = EditorGUILayout.BeginScrollView(textureListScrollPos);
369
370 foreach (TextureDetails tDetails in ActiveTextures)
371 {
372
373 GUILayout.BeginHorizontal ();
374 Texture tex = new Texture();
375 tex = tDetails.texture;
376 if(tDetails.texture.GetType() == typeof(Texture2DArray) || tDetails.texture.GetType() == typeof(Cubemap)){
377 tex = AssetPreview.GetMiniThumbnail(tDetails.texture);
378 }
379 GUILayout.Box(tex, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
380
381 if (tDetails.instance == true)
382 GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f);
383 if (tDetails.isgui == true)
384 GUI.color = new Color (defColor.r, 0.95f, 0.8f, 1.0f);
385 if (tDetails.isSky)
386 GUI.color = new Color (0.9f, defColor.g, defColor.b, 1.0f);
387 if(GUILayout.Button(tDetails.texture.name,GUILayout.Width(150)))
388 {
389 SelectObject(tDetails.texture,ctrlPressed);
390 }
391 GUI.color = defColor;
392
393 string sizeLabel=""+tDetails.texture.width+"x"+tDetails.texture.height;
394 if (tDetails.isCubeMap) sizeLabel+="x6";
395 if (tDetails.texture.GetType () == typeof(Texture2DArray))
396 sizeLabel+= "[]\n" + ((Texture2DArray)tDetails.texture).depth+"depths";
397 sizeLabel+=" - "+tDetails.mipMapCount+"mip\n"+FormatSizeString(tDetails.memSizeKB)+" - "+tDetails.format;
398
399 GUILayout.Label (sizeLabel,GUILayout.Width(120));
400
401 if(GUILayout.Button(tDetails.FoundInMaterials.Count+" Mat",GUILayout.Width(50)))
402 {
403 SelectObjects(tDetails.FoundInMaterials,ctrlPressed);
404 }
405
406 HashSet<Object> FoundObjects = new HashSet<Object>();
407 foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
408 foreach (Animator animator in tDetails.FoundInAnimators) FoundObjects.Add(animator.gameObject);
409 foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject);
410 foreach (MonoBehaviour script in tDetails.FoundInScripts) FoundObjects.Add(script.gameObject);
411 if (GUILayout.Button(FoundObjects.Count+" GO",GUILayout.Width(50)))
412 {
413 SelectObjects(new List<Object>(FoundObjects),ctrlPressed);
414 }
415
416 GUILayout.EndHorizontal();
417 }
418 if (ActiveTextures.Count>0)
419 {
420 EditorGUILayout.Space();
421 GUILayout.BeginHorizontal ();
422 //GUILayout.Box(" ",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));
423 if(GUILayout.Button("Select \n All",GUILayout.Width(ThumbnailWidth*2)))
424 {
425 List<Object> AllTextures=new List<Object>();
426 foreach (TextureDetails tDetails in ActiveTextures) AllTextures.Add(tDetails.texture);
427 SelectObjects(AllTextures,ctrlPressed);
428 }
429 EditorGUILayout.EndHorizontal();
430 }
431 EditorGUILayout.EndScrollView();
432 }
433
434 void ListMaterials()
435 {
436 materialListScrollPos = EditorGUILayout.BeginScrollView(materialListScrollPos);
437
438 foreach (MaterialDetails tDetails in ActiveMaterials)
439 {
440 if (tDetails.material!=null)
441 {
442 GUILayout.BeginHorizontal ();
443
444 GUILayout.Box(AssetPreview.GetAssetPreview(tDetails.material), GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
445
446 if (tDetails.instance == true)
447 GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f);
448 if (tDetails.isgui == true)
449 GUI.color = new Color (defColor.r, 0.95f, 0.8f, 1.0f);
450 if (tDetails.isSky)
451 GUI.color = new Color (0.9f, defColor.g, defColor.b, 1.0f);
452 if(GUILayout.Button(tDetails.material.name,GUILayout.Width(150)))
453 {
454 SelectObject(tDetails.material,ctrlPressed);
455 }
456 GUI.color = defColor;
457
458 string shaderLabel = tDetails.material.shader != null ?tDetails.material.shader.name : "no shader";
459 GUILayout.Label (shaderLabel, GUILayout.Width(200));
460
461 if(GUILayout.Button((tDetails.FoundInRenderers.Count + tDetails.FoundInGraphics.Count) +" GO",GUILayout.Width(50)))
462 {
463 List<Object> FoundObjects=new List<Object>();
464 foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
465 foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject);
466 SelectObjects(FoundObjects,ctrlPressed);
467 }
468
469
470 GUILayout.EndHorizontal();
471 }
472 }
473 EditorGUILayout.EndScrollView();
474 }
475
476 void ListMeshes()
477 {
478 meshListScrollPos = EditorGUILayout.BeginScrollView(meshListScrollPos);
479
480 foreach (MeshDetails tDetails in ActiveMeshDetails)
481 {
482 if (tDetails.mesh!=null)
483 {
484 GUILayout.BeginHorizontal ();
485 string name = tDetails.mesh.name;
486 if (name == null || name.Count() < 1)
487 name = tDetails.FoundInMeshFilters[0].gameObject.name;
488 if (tDetails.instance == true)
489 GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f);
490 if(GUILayout.Button(name,GUILayout.Width(150)))
491 {
492 SelectObject(tDetails.mesh,ctrlPressed);
493 }
494 GUI.color = defColor;
495 string sizeLabel=""+tDetails.mesh.vertexCount+" vert";
496
497 GUILayout.Label (sizeLabel,GUILayout.Width(100));
498
499
500 if(GUILayout.Button(tDetails.FoundInMeshFilters.Count + " GO",GUILayout.Width(50)))
501 {
502 List<Object> FoundObjects=new List<Object>();
503 foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters) FoundObjects.Add(meshFilter.gameObject);
504 SelectObjects(FoundObjects,ctrlPressed);
505 }
506 if (tDetails.FoundInSkinnedMeshRenderer.Count > 0) {
507 if (GUILayout.Button (tDetails.FoundInSkinnedMeshRenderer.Count + " skinned mesh GO", GUILayout.Width (140))) {
508 List<Object> FoundObjects = new List<Object> ();
509 foreach (SkinnedMeshRenderer skinnedMeshRenderer in tDetails.FoundInSkinnedMeshRenderer)
510 FoundObjects.Add (skinnedMeshRenderer.gameObject);
511 SelectObjects (FoundObjects, ctrlPressed);
512 }
513 } else {
514 GUI.color = new Color (defColor.r, defColor.g, defColor.b, 0.5f);
515 GUILayout.Label(" 0 skinned mesh");
516 GUI.color = defColor;
517 }
518
519
520 GUILayout.EndHorizontal();
521 }
522 }
523 EditorGUILayout.EndScrollView();
524 }
525
526 void ListMissing(){
527 missingListScrollPos = EditorGUILayout.BeginScrollView(missingListScrollPos);
528 foreach (MissingGraphic dMissing in MissingObjects) {
529 GUILayout.BeginHorizontal ();
530 if (GUILayout.Button (dMissing.name, GUILayout.Width (150)))
531 SelectObject (dMissing.Object, ctrlPressed);
532 GUILayout.Label ("missing ", GUILayout.Width(48));
533 switch (dMissing.type) {
534 case "mesh":
535 GUI.color = new Color (0.8f, 0.8f, defColor.b, 1.0f);
536 break;
537 case "sprite":
538 GUI.color = new Color (defColor.r, 0.8f, 0.8f, 1.0f);
539 break;
540 case "material":
541 GUI.color = new Color (0.8f, defColor.g, 0.8f, 1.0f);
542 break;
543 }
544 GUILayout.Label (dMissing.type);
545 GUI.color = defColor;
546 GUILayout.EndHorizontal ();
547 }
548 EditorGUILayout.EndScrollView();
549 }
550
551 string FormatSizeString(int memSizeKB)
552 {
553 if (memSizeKB<1024) return ""+memSizeKB+"k";
554 else
555 {
556 float memSizeMB=((float)memSizeKB)/1024.0f;
557 return memSizeMB.ToString("0.00")+"Mb";
558 }
559 }
560
561
562 TextureDetails FindTextureDetails(Texture tTexture)
563 {
564 foreach (TextureDetails tTextureDetails in ActiveTextures)
565 {
566 if (tTextureDetails.texture==tTexture) return tTextureDetails;
567 }
568 return null;
569
570 }
571
572 MaterialDetails FindMaterialDetails(Material tMaterial)
573 {
574 foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
575 {
576 if (tMaterialDetails.material==tMaterial) return tMaterialDetails;
577 }
578 return null;
579
580 }
581
582 MeshDetails FindMeshDetails(Mesh tMesh)
583 {
584 foreach (MeshDetails tMeshDetails in ActiveMeshDetails)
585 {
586 if (tMeshDetails.mesh==tMesh) return tMeshDetails;
587 }
588 return null;
589
590 }
591
592
593 void CheckResources()
594 {
595 ActiveTextures.Clear();
596 ActiveMaterials.Clear();
597 ActiveMeshDetails.Clear();
598 MissingObjects.Clear ();
599 thingsMissing = false;
600
601 Renderer[] renderers = FindObjects<Renderer>();
602
603 MaterialDetails skyMat = new MaterialDetails ();
604 skyMat.material = RenderSettings.skybox;
605 skyMat.isSky = true;
606 ActiveMaterials.Add (skyMat);
607
608 //Debug.Log("Total renderers "+renderers.Length);
609 foreach (Renderer renderer in renderers)
610 {
611 //Debug.Log("Renderer is "+renderer.name);
612 foreach (Material material in renderer.sharedMaterials)
613 {
614
615 MaterialDetails tMaterialDetails = FindMaterialDetails(material);
616 if (tMaterialDetails == null)
617 {
618 tMaterialDetails = new MaterialDetails();
619 tMaterialDetails.material = material;
620 ActiveMaterials.Add(tMaterialDetails);
621 }
622 tMaterialDetails.FoundInRenderers.Add(renderer);
623 }
624
625 if (renderer is SpriteRenderer)
626 {
627 SpriteRenderer tSpriteRenderer = (SpriteRenderer)renderer;
628
629 if (tSpriteRenderer.sprite != null) {
630 var tSpriteTextureDetail = GetTextureDetail (tSpriteRenderer.sprite.texture, renderer);
631 if (!ActiveTextures.Contains (tSpriteTextureDetail)) {
632 ActiveTextures.Add (tSpriteTextureDetail);
633 }
634 } else if (tSpriteRenderer.sprite == null) {
635 MissingGraphic tMissing = new MissingGraphic ();
636 tMissing.Object = tSpriteRenderer.transform;
637 tMissing.type = "sprite";
638 tMissing.name = tSpriteRenderer.transform.name;
639 MissingObjects.Add (tMissing);
640 thingsMissing = true;
641 }
642 }
643 }
644
645 if (IncludeGuiElements)
646 {
647 Graphic[] graphics = FindObjects<Graphic>();
648
649 foreach(Graphic graphic in graphics)
650 {
651 if (graphic.mainTexture)
652 {
653 var tSpriteTextureDetail = GetTextureDetail(graphic.mainTexture, graphic);
654 if (!ActiveTextures.Contains(tSpriteTextureDetail))
655 {
656 ActiveTextures.Add(tSpriteTextureDetail);
657 }
658 }
659
660 if (graphic.materialForRendering)
661 {
662 MaterialDetails tMaterialDetails = FindMaterialDetails(graphic.materialForRendering);
663 if (tMaterialDetails == null)
664 {
665 tMaterialDetails = new MaterialDetails();
666 tMaterialDetails.material = graphic.materialForRendering;
667 tMaterialDetails.isgui = true;
668 ActiveMaterials.Add(tMaterialDetails);
669 }
670 tMaterialDetails.FoundInGraphics.Add(graphic);
671 }
672 }
673 }
674
675 foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
676 {
677 Material tMaterial = tMaterialDetails.material;
678 if (tMaterial != null)
679 {
680 var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
681 foreach (Object obj in dependencies)
682 {
683 if (obj is Texture)
684 {
685 Texture tTexture = obj as Texture;
686 var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMaterialDetails);
687 tTextureDetail.isSky = tMaterialDetails.isSky;
688 tTextureDetail.instance = tMaterialDetails.instance;
689 tTextureDetail.isgui = tMaterialDetails.isgui;
690 ActiveTextures.Add(tTextureDetail);
691 }
692 }
693
694 //if the texture was downloaded, it won't be included in the editor dependencies
695 if (tMaterial.HasProperty ("_MainTex")) {
696 if (tMaterial.mainTexture != null && !dependencies.Contains (tMaterial.mainTexture)) {
697 var tTextureDetail = GetTextureDetail (tMaterial.mainTexture, tMaterial, tMaterialDetails);
698 ActiveTextures.Add (tTextureDetail);
699 }
700 }
701 }
702 }
703
704
705 MeshFilter[] meshFilters = FindObjects<MeshFilter>();
706
707 foreach (MeshFilter tMeshFilter in meshFilters)
708 {
709 Mesh tMesh = tMeshFilter.sharedMesh;
710 if (tMesh != null)
711 {
712 MeshDetails tMeshDetails = FindMeshDetails(tMesh);
713 if (tMeshDetails == null)
714 {
715 tMeshDetails = new MeshDetails();
716 tMeshDetails.mesh = tMesh;
717 ActiveMeshDetails.Add(tMeshDetails);
718 }
719 tMeshDetails.FoundInMeshFilters.Add(tMeshFilter);
720 } else if (tMesh == null && tMeshFilter.transform.GetComponent("TextContainer")== null) {
721 MissingGraphic tMissing = new MissingGraphic ();
722 tMissing.Object = tMeshFilter.transform;
723 tMissing.type = "mesh";
724 tMissing.name = tMeshFilter.transform.name;
725 MissingObjects.Add (tMissing);
726 thingsMissing = true;
727 }
728
729 var meshRenderrer = tMeshFilter.transform.GetComponent<MeshRenderer>();
730
731 if (meshRenderrer == null || meshRenderrer.sharedMaterial == null) {
732 MissingGraphic tMissing = new MissingGraphic ();
733 tMissing.Object = tMeshFilter.transform;
734 tMissing.type = "material";
735 tMissing.name = tMeshFilter.transform.name;
736 MissingObjects.Add (tMissing);
737 thingsMissing = true;
738 }
739 }
740
741 SkinnedMeshRenderer[] skinnedMeshRenderers = FindObjects<SkinnedMeshRenderer>();
742
743 foreach (SkinnedMeshRenderer tSkinnedMeshRenderer in skinnedMeshRenderers)
744 {
745 Mesh tMesh = tSkinnedMeshRenderer.sharedMesh;
746 if (tMesh != null)
747 {
748 MeshDetails tMeshDetails = FindMeshDetails(tMesh);
749 if (tMeshDetails == null)
750 {
751 tMeshDetails = new MeshDetails();
752 tMeshDetails.mesh = tMesh;
753 ActiveMeshDetails.Add(tMeshDetails);
754 }
755 tMeshDetails.FoundInSkinnedMeshRenderer.Add(tSkinnedMeshRenderer);
756 } else if (tMesh == null) {
757 MissingGraphic tMissing = new MissingGraphic ();
758 tMissing.Object = tSkinnedMeshRenderer.transform;
759 tMissing.type = "mesh";
760 tMissing.name = tSkinnedMeshRenderer.transform.name;
761 MissingObjects.Add (tMissing);
762 thingsMissing = true;
763 }
764 if (tSkinnedMeshRenderer.sharedMaterial == null) {
765 MissingGraphic tMissing = new MissingGraphic ();
766 tMissing.Object = tSkinnedMeshRenderer.transform;
767 tMissing.type = "material";
768 tMissing.name = tSkinnedMeshRenderer.transform.name;
769 MissingObjects.Add (tMissing);
770 thingsMissing = true;
771 }
772 }
773
774 if (IncludeSpriteAnimations)
775 {
776 Animator[] animators = FindObjects<Animator>();
777 foreach (Animator anim in animators)
778 {
779 #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
780 UnityEditorInternal.AnimatorController ac = anim.runtimeAnimatorController as UnityEditorInternal.AnimatorController;
781 #elif UNITY_5 || UNITY_5_3_OR_NEWER
782 UnityEditor.Animations.AnimatorController ac = anim.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
783 #endif
784
785 //Skip animators without layers, this can happen if they don't have an animator controller.
786 if (!ac || ac.layers == null || ac.layers.Length == 0)
787 continue;
788
789 for (int x = 0; x < anim.layerCount; x++)
790 {
791 #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
792 UnityEditorInternal.StateMachine sm = ac.GetLayer(x).stateMachine;
793 int cnt = sm.stateCount;
794 #elif UNITY_5 || UNITY_5_3_OR_NEWER
795 UnityEditor.Animations.AnimatorStateMachine sm = ac.layers[x].stateMachine;
796 int cnt = sm.states.Length;
797 #endif
798
799 for (int i = 0; i < cnt; i++)
800 {
801 #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
802 UnityEditorInternal.State state = sm.GetState(i);
803 Motion m = state.GetMotion();
804 #elif UNITY_5 || UNITY_5_3_OR_NEWER
805 UnityEditor.Animations.AnimatorState state = sm.states[i].state;
806 Motion m = state.motion;
807 #endif
808 if (m != null)
809 {
810 AnimationClip clip = m as AnimationClip;
811
812 if (clip != null)
813 {
814 EditorCurveBinding[] ecbs = AnimationUtility.GetObjectReferenceCurveBindings(clip);
815
816 foreach (EditorCurveBinding ecb in ecbs)
817 {
818 if (ecb.propertyName == "m_Sprite")
819 {
820 foreach (ObjectReferenceKeyframe keyframe in AnimationUtility.GetObjectReferenceCurve(clip, ecb))
821 {
822 Sprite tSprite = keyframe.value as Sprite;
823
824 if (tSprite != null)
825 {
826 var tTextureDetail = GetTextureDetail(tSprite.texture, anim);
827 if (!ActiveTextures.Contains(tTextureDetail))
828 {
829 ActiveTextures.Add(tTextureDetail);
830 }
831 }
832 }
833 }
834 }
835 }
836 }
837 }
838 }
839
840 }
841 }
842
843 if (IncludeScriptReferences)
844 {
845 MonoBehaviour[] scripts = FindObjects<MonoBehaviour>();
846 foreach (MonoBehaviour script in scripts)
847 {
848 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; // only public non-static fields are bound to by Unity.
849 FieldInfo[] fields = script.GetType().GetFields(flags);
850
851 foreach (FieldInfo field in fields)
852 {
853 System.Type fieldType = field.FieldType;
854 if (fieldType == typeof(Sprite))
855 {
856 Sprite tSprite = field.GetValue(script) as Sprite;
857 if (tSprite != null)
858 {
859 var tSpriteTextureDetail = GetTextureDetail(tSprite.texture, script);
860 if (!ActiveTextures.Contains(tSpriteTextureDetail))
861 {
862 ActiveTextures.Add(tSpriteTextureDetail);
863 }
864 }
865 }if (fieldType == typeof(Mesh))
866 {
867 Mesh tMesh = field.GetValue(script) as Mesh;
868 if (tMesh != null)
869 {
870 MeshDetails tMeshDetails = FindMeshDetails(tMesh);
871 if (tMeshDetails == null)
872 {
873 tMeshDetails = new MeshDetails();
874 tMeshDetails.mesh = tMesh;
875 tMeshDetails.instance = true;
876 ActiveMeshDetails.Add(tMeshDetails);
877 }
878 }
879 }if (fieldType == typeof(Material))
880 {
881 Material tMaterial = field.GetValue(script) as Material;
882 if (tMaterial != null)
883 {
884 MaterialDetails tMatDetails = FindMaterialDetails(tMaterial);
885 if (tMatDetails == null)
886 {
887 tMatDetails = new MaterialDetails();
888 tMatDetails.instance = true;
889 tMatDetails.material = tMaterial;
890 if(!ActiveMaterials.Contains(tMatDetails))
891 ActiveMaterials.Add(tMatDetails);
892 }
893 if (tMaterial.mainTexture)
894 {
895 var tSpriteTextureDetail = GetTextureDetail(tMaterial.mainTexture);
896 if (!ActiveTextures.Contains(tSpriteTextureDetail))
897 {
898 ActiveTextures.Add(tSpriteTextureDetail);
899 }
900 }
901 var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
902 foreach (Object obj in dependencies)
903 {
904 if (obj is Texture)
905 {
906 Texture tTexture = obj as Texture;
907 var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMatDetails);
908 if(!ActiveTextures.Contains(tTextureDetail))
909 ActiveTextures.Add(tTextureDetail);
910 }
911 }
912 }
913 }
914 }
915 }
916 }
917
918 TotalTextureMemory = 0;
919 foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB;
920
921 TotalMeshVertices = 0;
922 foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount;
923
924 // Sort by size, descending
925 ActiveTextures.Sort(delegate(TextureDetails details1, TextureDetails details2) { return details2.memSizeKB - details1.memSizeKB; });
926 ActiveTextures = ActiveTextures.Distinct().ToList();
927 ActiveMeshDetails.Sort(delegate(MeshDetails details1, MeshDetails details2) { return details2.mesh.vertexCount - details1.mesh.vertexCount; });
928
929 collectedInPlayingMode = Application.isPlaying;
930 }
931
932 private static GameObject[] GetAllRootGameObjects()
933 {
934 #if !UNITY_5 && !UNITY_5_3_OR_NEWER
935 return UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects().ToArray();
936 #else
937 List<GameObject> allGo = new List<GameObject>();
938 for (int sceneIdx = 0; sceneIdx < UnityEngine.SceneManagement.SceneManager.sceneCount; ++sceneIdx){
939 allGo.AddRange( UnityEngine.SceneManagement.SceneManager.GetSceneAt(sceneIdx).GetRootGameObjects().ToArray() );
940 }
941 return allGo.ToArray();
942 #endif
943 }
944
945 private T[] FindObjects<T>() where T : Object
946 {
947 if (IncludeDisabledObjects) {
948 List<T> meshfilters = new List<T> ();
949 GameObject[] allGo = GetAllRootGameObjects();
950 foreach (GameObject go in allGo) {
951 Transform[] tgo = go.GetComponentsInChildren<Transform> (true).ToArray ();
952 foreach (Transform tr in tgo) {
953 if (tr.GetComponent<T> ())
954 meshfilters.Add (tr.GetComponent<T> ());
955 }
956 }
957 return (T[])meshfilters.ToArray ();
958 }
959 else
960 return (T[])FindObjectsOfType(typeof(T));
961 }
962
963 private TextureDetails GetTextureDetail(Texture tTexture, Material tMaterial, MaterialDetails tMaterialDetails)
964 {
965 TextureDetails tTextureDetails = GetTextureDetail(tTexture);
966
967 tTextureDetails.FoundInMaterials.Add(tMaterial);
968 foreach (Renderer renderer in tMaterialDetails.FoundInRenderers)
969 {
970 if (!tTextureDetails.FoundInRenderers.Contains(renderer)) tTextureDetails.FoundInRenderers.Add(renderer);
971 }
972 return tTextureDetails;
973 }
974
975 private TextureDetails GetTextureDetail(Texture tTexture, Renderer renderer)
976 {
977 TextureDetails tTextureDetails = GetTextureDetail(tTexture);
978
979 tTextureDetails.FoundInRenderers.Add(renderer);
980 return tTextureDetails;
981 }
982
983 private TextureDetails GetTextureDetail(Texture tTexture, Animator animator)
984 {
985 TextureDetails tTextureDetails = GetTextureDetail(tTexture);
986
987 tTextureDetails.FoundInAnimators.Add(animator);
988 return tTextureDetails;
989 }
990
991 private TextureDetails GetTextureDetail(Texture tTexture, Graphic graphic)
992 {
993 TextureDetails tTextureDetails = GetTextureDetail(tTexture);
994
995 tTextureDetails.FoundInGraphics.Add(graphic);
996 return tTextureDetails;
997 }
998
999 private TextureDetails GetTextureDetail(Texture tTexture, MonoBehaviour script)
1000 {
1001 TextureDetails tTextureDetails = GetTextureDetail(tTexture);
1002
1003 tTextureDetails.FoundInScripts.Add(script);
1004 return tTextureDetails;
1005 }
1006
1007 private TextureDetails GetTextureDetail(Texture tTexture)
1008 {
1009 TextureDetails tTextureDetails = FindTextureDetails(tTexture);
1010 if (tTextureDetails == null)
1011 {
1012 tTextureDetails = new TextureDetails();
1013 tTextureDetails.texture = tTexture;
1014 tTextureDetails.isCubeMap = tTexture is Cubemap;
1015
1016 int memSize = CalculateTextureSizeBytes(tTexture);
1017
1018 TextureFormat tFormat = TextureFormat.RGBA32;
1019 int tMipMapCount = 1;
1020 if (tTexture is Texture2D)
1021 {
1022 tFormat = (tTexture as Texture2D).format;
1023 tMipMapCount = (tTexture as Texture2D).mipmapCount;
1024 }
1025 if (tTexture is Cubemap)
1026 {
1027 tFormat = (tTexture as Cubemap).format;
1028 memSize = 8 * tTexture.height * tTexture.width;
1029 }
1030 if(tTexture is Texture2DArray){
1031 tFormat = (tTexture as Texture2DArray).format;
1032 tMipMapCount = 10;
1033 }
1034
1035 tTextureDetails.memSizeKB = memSize/1024;
1036 tTextureDetails.format = tFormat;
1037 tTextureDetails.mipMapCount = tMipMapCount;
1038
1039 }
1040
1041 return tTextureDetails;
1042 }
1043
1044 }
ResourceChecker
p>
download address: https://github.com/handcircus/Unity-Resource-Checker p>
use: Unity navigation menu bar select Windows -> Resource Checker, click to get
p>
ii, UnityAssetCleaner
super diao Fried day plug-in, strongly recommended to use, there are three types of cleaning up the resource mode, more importantly, it will remove the resources under the assets,
will automatically delete the file backup a package package, so you no longer need to worry about mistakenly delete useful resources, mistakenly delete, the biggest thing is the package package guide in.
code:
1 /**
2 asset cleaner
3 Copyright (c) 2015 Tatsuhiko Yamamura
4
5 This software is released under the MIT License.
6 http://opensource.org/licenses/mit-license.php
7 */
8 using UnityEngine;
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Linq;
12 using UnityEditor;
13 using System.IO;
14 using System.Text.RegularExpressions;
15
16 namespace AssetClean
17 {
18 public class AssetCollector
19 {
20 public List<string> deleteFileList = new List<string> ();
21 ClassReferenceCollection classCollection = new ClassReferenceCollection ();
22 ShaderReferenceCollection shaderCollection = new ShaderReferenceCollection ();
23
24 public bool useCodeStrip = true;
25 public bool saveEditorExtensions = true;
26
27 public void Collection ()
28 {
29 try {
30 deleteFileList.Clear ();
31
32 if( useCodeStrip ){
33 classCollection.Collection ();
34 }
35 shaderCollection.Collection ();
36
37 // Find assets
38 var files = Directory.GetFiles ("Assets", "*.*", SearchOption.AllDirectories)
39 .Where (item => Path.GetExtension (item) != ".meta")
40 .Where (item => Path.GetExtension (item) != ".js")
41 .Where (item => Path.GetExtension (item) != ".dll")
42 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Gizmos[\\/\\\\]") == false)
43 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Plugins[\\/\\\\]Android[\\/\\\\]") == false)
44 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Plugins[\\/\\\\]iOS[\\/\\\\]") == false)
45 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Resources[\\/\\\\]") == false);
46
47 if( useCodeStrip == false ){
48 files = files.Where( item => Path.GetExtension(item) != ".cs");
49 }
50
51 foreach (var path in files) {
52 var guid = AssetDatabase.AssetPathToGUID (path);
53 deleteFileList.Add (guid);
54 }
55 EditorUtility.DisplayProgressBar ("checking", "collection all files", 0.2f);
56 UnregistReferenceFromResources();
57
58 EditorUtility.DisplayProgressBar ("checking", "check reference from resources", 0.4f);
59 UnregistReferenceFromScenes();
60
61 EditorUtility.DisplayProgressBar ("checking", "check reference from scenes", 0.6f);
62 if( saveEditorExtensions ){
63 UnregistEditorCodes();
64 }
65 } finally {
66 EditorUtility.ClearProgressBar ();
67 }
68 }
69 void UnregistReferenceFromResources()
70 {
71 var resourcesFiles = Directory.GetFiles ("Assets", "*.*", SearchOption.AllDirectories)
72 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Resources[\\/\\\\]") == true)
73 .Where (item => Path.GetExtension (item) != ".meta")
74 .ToArray ();
75 foreach (var path in AssetDatabase.GetDependencies (resourcesFiles)) {
76 UnregistFromDelteList (AssetDatabase.AssetPathToGUID(path));
77 }
78 }
79
80 void UnregistReferenceFromScenes()
81 {
82 // Exclude objects that reference from scenes.
83 var scenes = EditorBuildSettings.scenes
84 .Where (item => item.enabled == true)
85 .Select (item => item.path)
86 .ToArray ();
87 foreach (var path in AssetDatabase.GetDependencies (scenes)) {
88 if( saveEditorExtensions == false ){
89 Debug.Log(path);
90 }
91 UnregistFromDelteList (AssetDatabase.AssetPathToGUID(path));
92 }
93 }
94
95 void UnregistEditorCodes()
96 {
97 // Exclude objects that reference from Editor API
98 var editorcodes = Directory.GetFiles ("Assets", "*.cs", SearchOption.AllDirectories)
99 .Where (item => Regex.IsMatch (item, "[\\/\\\\]Editor[\\/\\\\]") == true)
100 .ToArray ();
101
102 var undeleteClassList = classCollection.codeFileList
103 .Where (codefile => codefile.Value.Any( guid => deleteFileList.Contains(guid)) == false)
104 .Select( item => item.Key );
105
106 EditorUtility.DisplayProgressBar ("checking", "check reference from editor codes", 0.8f);
107
108 foreach (var path in editorcodes) {
109 var code = File.ReadAllText (path);
110 code = Regex.Replace(code, "//.*[\\n\\r]", "");
111 code = Regex.Replace(code, "/\\*.*[\\n\\r]\\*/", "");
112 if (Regex.IsMatch (code, "(\\[MenuItem|AssetPostprocessor|EditorWindow)")) {
113 UnregistFromDelteList ( AssetDatabase.AssetPathToGUID(path));
114 continue;
115 }
116
117 foreach (var undeleteClass in undeleteClassList) {
118 if (Regex.IsMatch (code, string.Format ("\\[CustomEditor.*\\(\\s*{0}\\s*\\).*\\]", undeleteClass.Name))) {
119 UnregistFromDelteList (path);
120 continue;
121 }
122 }
123 }
124 }
125
126 void UnregistFromDelteList (string guid)
127 {
128 if (deleteFileList.Contains (guid) == false) {
129 return;
130 }
131 deleteFileList.Remove (guid);
132
133 if (classCollection.references.ContainsKey (guid) == true) {
134
135 foreach (var type in classCollection.references[guid]) {
136 var codePaths = classCollection.codeFileList [type];
137 foreach( var codePath in codePaths){
138 UnregistFromDelteList (codePath);
139 }
140 }
141 }
142
143 if (shaderCollection.shaderFileList.ContainsValue (guid)) {
144 var shader = shaderCollection.shaderFileList.First (item => item.Value == guid);
145 var shaderAssets = shaderCollection.shaderReferenceList [shader.Key];
146 foreach (var shaderPath in shaderAssets) {
147 UnregistFromDelteList (shaderPath);
148 }
149 }
150 }
151 }
152 }
AssetCollector
1 /**
2 asset cleaner
3 Copyright (c) 2015 Tatsuhiko Yamamura
4
5 This software is released under the MIT License.
6 http://opensource.org/licenses/mit-license.php
7 */
8 using UnityEngine;
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Text.RegularExpressions;
12 using UnityEditor;
13 using System.IO;
14 using System.Reflection;
15 using System.Linq;
16
17 namespace AssetClean
18 {
19 public class ClassReferenceCollection
20 {
21 // type : guid
22 public Dictionary<System.Type, List<string>> codeFileList = new Dictionary<System.Type, List<string>> ();
23 // guid : types
24 public Dictionary<string, List<System.Type>> references = new Dictionary<string, List<System.Type>> ();
25
26 public void Collection ()
27 {
28 references.Clear ();
29 EditorUtility.DisplayProgressBar ("checking", "collection all type", 0);
30
31 // Connect the files and class.
32 var codes = Directory.GetFiles ("Assets", "*.cs", SearchOption.AllDirectories);
33 // connect each classes.
34 var firstPassList = new List<string>();
35 if( Directory.Exists ("Assets/Plugins") )
36 firstPassList.AddRange( Directory.GetFiles ("Assets/Plugins", "*.cs", SearchOption.AllDirectories));
37 if( Directory.Exists ("Assets/Standard Assets") )
38 firstPassList.AddRange( Directory.GetFiles ("Assets/Standard Assets", "*.cs", SearchOption.AllDirectories));
39
40 var allFirstpassTypes = collectionAllFastspassClasses ();
41 CollectionCodeFileDictionary (allFirstpassTypes, firstPassList.ToArray());
42
43
44 var alltypes = CollectionAllClasses ();
45 CollectionCodeFileDictionary (alltypes, codes.ToArray());
46 alltypes.AddRange (allFirstpassTypes);
47
48 int count = 0;
49 foreach (var codepath in firstPassList) {
50 CollectionReferenceClasses (AssetDatabase.AssetPathToGUID (codepath), allFirstpassTypes);
51 EditorUtility.DisplayProgressBar ("checking", "analytics codes", ((float)++count/codes.Length) * 0.5f + 0.5f);
52 }
53 count = 0;
54 foreach (var codepath in codes) {
55 CollectionReferenceClasses (AssetDatabase.AssetPathToGUID (codepath), alltypes);
56 EditorUtility.DisplayProgressBar ("checking", "analytics codes", ((float)++count/codes.Length) * 0.5f);
57 }
58 }
59
60 void CollectionCodeFileDictionary (List<System.Type> alltypes, string[] codes)
61 {
62 float count = 1;
63 foreach (var codePath in codes) {
64 EditorUtility.DisplayProgressBar ("checking", "search files", count++ / codes.Length);
65
66 // connect file and classes.
67 var code = System.IO.File.ReadAllText (codePath);
68 code = Regex.Replace(code, "//.*[\\n\\r]", "");
69 code = Regex.Replace(code, "/\\*.*[\\n\\r]\\*/", "");
70
71 foreach (var type in alltypes) {
72
73 if( codeFileList.ContainsKey(type ) == false ){
74 codeFileList.Add(type, new List<string>());
75 }
76 var list = codeFileList[type];
77
78 if (string.IsNullOrEmpty (type.Namespace) == false) {
79 var namespacepattern = string.Format ("namespace[\\s.]{0}[{{\\s\\n]", type.Namespace);
80 if (Regex.IsMatch (code, namespacepattern) == false) {
81 continue;
82 }
83 }
84
85 string typeName = type.IsGenericTypeDefinition ?type.GetGenericTypeDefinition ().Name.Split ('`') [0] : type.Name;
86 if (Regex.IsMatch (code, string.Format ("class\\s*{0}?[\\s:<{{]", typeName))) {
87 list.Add( AssetDatabase.AssetPathToGUID(codePath) );
88 continue;
89 }
90
91 if (Regex.IsMatch (code, string.Format ("struct\\s*{0}[\\s:<{{]", typeName))) {
92 list.Add( AssetDatabase.AssetPathToGUID(codePath) );
93 continue;
94 }
95
96 if (Regex.IsMatch (code, string.Format ("enum\\s*{0}[\\s{{]", type.Name))) {
97 list.Add( AssetDatabase.AssetPathToGUID(codePath) );
98 continue;
99 }
100
101 if (Regex.IsMatch (code, string.Format ("delegate\\s*{0}\\s\\(", type.Name))) {
102 list.Add( AssetDatabase.AssetPathToGUID(codePath) );
103 continue;
104 }
105 }
106 }
107 }
108
109 List<System.Type> CollectionAllClasses ()
110 {
111 List<System.Type> alltypes = new List<System.Type> ();
112
113 if (File.Exists ("Library/ScriptAssemblies/Assembly-CSharp.dll"))
114 alltypes.AddRange (Assembly.LoadFile ("Library/ScriptAssemblies/Assembly-CSharp.dll").GetTypes ());
115 if (File.Exists ("Library/ScriptAssemblies/Assembly-CSharp-Editor.dll"))
116 alltypes.AddRange (Assembly.LoadFile ("Library/ScriptAssemblies/Assembly-CSharp-Editor.dll").GetTypes ());
117
118 return alltypes .ToList ();
119 }
120
121 List<System.Type> collectionAllFastspassClasses()
122 {
123 List<System.Type> alltypes = new List<System.Type> ();
124 if (File.Exists ("Library/ScriptAssemblies/Assembly-CSharp-firstpass.dll"))
125 alltypes.AddRange (Assembly.LoadFile ("Library/ScriptAssemblies/Assembly-CSharp-firstpass.dll").GetTypes ());
126 if (File.Exists ("Library/ScriptAssemblies/Assembly-CSharp-Editor-firstpass.dll"))
127 alltypes.AddRange (Assembly.LoadFile ("Library/ScriptAssemblies/Assembly-CSharp-Editor-firstpass.dll").GetTypes ());
128 return alltypes;
129 }
130
131 void CollectionReferenceClasses (string guid, List<System.Type> types)
132 {
133 var codePath = AssetDatabase.GUIDToAssetPath(guid);
134 if (string.IsNullOrEmpty (codePath) || references.ContainsKey (guid) || File.Exists(codePath)==false) {
135 return;
136 }
137
138 var code = System.IO.File.ReadAllText (codePath);
139 code = Regex.Replace(code, "//.*[\\n\\r]", "");
140 code = Regex.Replace(code, "/\\*.*[\\n\\r]\\*/", "");
141
142 var list = new List<System.Type> ();
143 references [guid] = list;
144
145 foreach (var type in types) {
146
147 if (string.IsNullOrEmpty (type.Namespace) == false) {
148 var namespacepattern = string.Format ("[namespace|using][\\s\\.]{0}[{{\\s\\r\\n\\r;]", type.Namespace);
149 if (Regex.IsMatch (code, namespacepattern) == false) {
150 continue;
151 }
152 }
153
154 if (codeFileList.ContainsKey (type) == false) {
155 continue;
156 }
157
158 string match = string.Empty;
159 if (type.IsGenericTypeDefinition) {
160 string typeName = type.GetGenericTypeDefinition ().Name.Split ('`') [0];
161 match = string.Format ("[\\]\\[\\.\\s<(]{0}[\\.\\s\\n\\r>,<(){{]", typeName);
162 } else {
163 match = string.Format ("[\\]\\[\\.\\s<(]{0}[\\.\\s\\n\\r>,<(){{\\]]", type.Name.Replace("Attribute", ""));
164 }
165 if (Regex.IsMatch (code, match)) {
166 list.Add (type);
167 var typeGuid = codeFileList[type];
168 foreach( var referenceGuid in typeGuid){
169 CollectionReferenceClasses (referenceGuid, types);
170 }
171 }
172 }
173 }
174 }
175 }
ClassReferenceCollection
1 /**
2 asset cleaner
3 Copyright (c) 2015 Tatsuhiko Yamamura
4
5 This software is released under the MIT License.
6 http://opensource.org/licenses/mit-license.php
7 */
8 using UnityEngine;
9 using System.Collections;
10 using System.Collections.Generic;
11 using UnityEditor;
12 using System.IO;
13 using System.Linq;
14
15 namespace AssetClean
16 {
17 public class FindUnusedAssets : EditorWindow
18 {
19 AssetCollector collection = new AssetCollector ();
20 List<DeleteAsset> deleteAssets = new List<DeleteAsset> ();
21 Vector2 scroll;
22
23 [MenuItem("Assets/Delete Unused Assets/only resource", false, 50)]
24 static void InitWithoutCode ()
25 {
26 var window = FindUnusedAssets.CreateInstance<FindUnusedAssets> ();
27 window.collection.useCodeStrip = false;
28 window.collection.Collection ();
29 window.CopyDeleteFileList (window.collection.deleteFileList);
30
31 window.Show ();
32 }
33
34 [MenuItem("Assets/Delete Unused Assets/unused by editor", false, 51)]
35 static void InitWithout ()
36 {
37 var window = FindUnusedAssets.CreateInstance<FindUnusedAssets> ();
38 window.collection.Collection ();
39 window.CopyDeleteFileList (window.collection.deleteFileList);
40
41 window.Show ();
42 }
43
44 [MenuItem("Assets/Delete Unused Assets/unused by game", false, 52)]
45 static void Init ()
46 {
47 var window = FindUnusedAssets.CreateInstance<FindUnusedAssets> ();
48 window.collection.saveEditorExtensions = false;
49 window.collection.Collection ();
50 window.CopyDeleteFileList (window.collection.deleteFileList);
51
52 window.Show ();
53 }
54
55 void OnGUI ()
56 {
57 using (var horizonal = new EditorGUILayout.HorizontalScope("box")) {
58 EditorGUILayout.LabelField ("delete unreference assets from buildsettings and resources");
59
60 if (GUILayout.Button ("Delete", GUILayout.Width (120), GUILayout.Height (40)) && deleteAssets.Count != 0) {
61 RemoveFiles ();
62 Close ();
63 }
64 }
65
66 using (var scrollScope = new EditorGUILayout.ScrollViewScope(scroll)) {
67 scroll = scrollScope.scrollPosition;
68 foreach (var asset in deleteAssets) {
69 if (string.IsNullOrEmpty (asset.path)) {
70 continue;
71 }
72
73 using (var horizonal = new EditorGUILayout.HorizontalScope()) {
74 asset.isDelete = EditorGUILayout.Toggle (asset.isDelete, GUILayout.Width (20));
75 var icon = AssetDatabase.GetCachedIcon (asset.path);
76 GUILayout.Label (icon, GUILayout.Width (20), GUILayout.Height (20));
77 if (GUILayout.Button (asset.path, EditorStyles.largeLabel)) {
78 Selection.activeObject = AssetDatabase.LoadAssetAtPath<Object> (asset.path);
79 }
80 }
81 }
82 }
83
84 }
85
86 static void CleanDir()
87 {
88 RemoveEmptyDirectry ("Assets");
89 AssetDatabase.Refresh ();
90 }
91
92 void CopyDeleteFileList(IEnumerable<string> deleteFileList)
93 {
94 foreach (var asset in deleteFileList) {
95 var filePath = AssetDatabase.GUIDToAssetPath (asset);
96 if (string.IsNullOrEmpty (filePath) == false) {
97 deleteAssets.Add (new DeleteAsset (){ path = filePath});
98 }
99 }
100 }
101
102 void RemoveFiles ()
103 {
104 try {
105 string exportDirectry = "BackupUnusedAssets";
106 Directory.CreateDirectory (exportDirectry);
107 var files = deleteAssets.Where (item => item.isDelete == true).Select (item => item.path).ToArray ();
108 string backupPackageName = exportDirectry + "/package" + System.DateTime.Now.ToString ("yyyyMMddHHmmss") + ".unitypackage";
109 EditorUtility.DisplayProgressBar ("export package", backupPackageName, 0);
110 AssetDatabase.ExportPackage (files, backupPackageName);
111
112 int i = 0;
113 int length = deleteAssets.Count;
114
115 foreach (var assetPath in files) {
116 i++;
117 EditorUtility.DisplayProgressBar ("delete unused assets", assetPath, (float)i / length);
118 AssetDatabase.DeleteAsset (assetPath);
119 }
120
121 EditorUtility.DisplayProgressBar ("clean directory", "", 1);
122 foreach (var dir in Directory.GetDirectories("Assets")) {
123 RemoveEmptyDirectry (dir);
124 }
125
126 System.Diagnostics.Process.Start (exportDirectry);
127
128 AssetDatabase.Refresh ();
129 }
130 catch( System.Exception e ){
131 Debug.Log(e.Message);
132 }finally {
133 EditorUtility.ClearProgressBar ();
134 }
135 }
136
137 static void RemoveEmptyDirectry (string path)
138 {
139 var dirs = Directory.GetDirectories (path);
140 foreach (var dir in dirs) {
141 RemoveEmptyDirectry (dir);
142 }
143
144 var files = Directory.GetFiles (path, "*", SearchOption.TopDirectoryOnly).Where (item => Path.GetExtension (item) != ".meta");
145 if (files.Count () == 0 && Directory.GetDirectories (path).Count () == 0) {
146 var metaFile = AssetDatabase.GetTextMetaFilePathFromAssetPath(path);
147 UnityEditor.FileUtil.DeleteFileOrDirectory (path);
148 UnityEditor.FileUtil.DeleteFileOrDirectory (metaFile);
149 }
150 }
151
152 class DeleteAsset
153 {
154 public bool isDelete = true;
155 public string path;
156 }
157 }
158 }
FindUnusedAssets
1 /**
2 asset cleaner
3 Copyright (c) 2015 Tatsuhiko Yamamura
4
5 This software is released under the MIT License.
6 http://opensource.org/licenses/mit-license.php
7 */
8 using UnityEngine;
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.IO;
12 using System.Text.RegularExpressions;
13 using UnityEditor;
14
15 namespace AssetClean
16 {
17 public class ShaderReferenceCollection
18 {
19 // shader name/shader file guid
20 public Dictionary<string, string> shaderFileList = new Dictionary<string, string> ();
21 public Dictionary<string, List<string> > shaderReferenceList = new Dictionary<string, List<string>> ();
22
23 public void Collection ()
24 {
25 CollectionShaderFiles ();
26 CheckReference ();
27 }
28
29 void CollectionShaderFiles ()
30 {
31 var shaderFiles = Directory.GetFiles ("Assets", "*.shader", SearchOption.AllDirectories);
32 foreach (var shaderFilePath in shaderFiles) {
33 var code = File.ReadAllText (shaderFilePath);
34 var match = Regex.Match (code, "Shader \"(?<name>.*)\"");
35 if (match.Success) {
36 var shaderName = match.Groups ["name"].ToString ();
37 if (shaderFileList.ContainsKey (shaderName) == false) {
38 shaderFileList.Add (shaderName, AssetDatabase.AssetPathToGUID(shaderFilePath));
39 }
40 }
41 }
42
43 var cgFiles = Directory.GetFiles ("Assets", "*.cg", SearchOption.AllDirectories);
44 foreach (var cgFilePath in cgFiles) {
45 var file = Path.GetFileName (cgFilePath);
46 shaderFileList.Add (file, cgFilePath);
47 }
48
49 var cgincFiles = Directory.GetFiles ("Assets", "*.cginc", SearchOption.AllDirectories);
50 foreach (var cgincPath in cgincFiles) {
51 var file = Path.GetFileName (cgincPath);
52 shaderFileList.Add (file, cgincPath);
53 }
54 }
55
56 void CheckReference ()
57 {
58 foreach (var shader in shaderFileList) {
59 var shaderFilePath = AssetDatabase.GUIDToAssetPath(shader.Value);
60 var shaderName = shader.Key;
61
62 List<string> referenceList = new List<string> ();
63 shaderReferenceList.Add (shaderName, referenceList);
64
65 var code = File.ReadAllText (shaderFilePath);
66
67 foreach (var checkingShaderName in shaderFileList.Keys) {
68 if (Regex.IsMatch (code, string.Format ("{0}", checkingShaderName))) {
69 var filePath = shaderFileList [checkingShaderName];
70 referenceList.Add (filePath);
71 }
72 }
73 }
74 }
75 }
76 }
ShaderReferenceCollection
Reality cn/tool-unityassetcleaner
is one of the few reality cleaners
use: Unity navigation menu bar select Assets-> Delete Unused Assets
three modes, select a suitable, and then click Delete, easy to fix
p>
reproduced in: https://www.cnblogs.com/Jason-c/p/7526326.html p>