• unity 自动删除未引用的Assets下的资源


    随着时间的堆积,项目中Assets文件夹下的资源会变得越来越繁杂,有些贴图、材质啥的可能压根没有使用过,但是又不敢轻易去删除。

    这里分享两个插件,用于管理这些资源。

    一、ResourceChecker

    这个插件的强大之处就在于它能够查找当前场景中的所有引用个资源,并快速定位,然后把未定位到的资源手动删掉就行了。

    代码

       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 (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+= "[]
    " + ((Texture2DArray)tDetails.texture).depth+"depths";
     397             sizeLabel+=" - "+tDetails.mipMapCount+"mip
    "+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 
     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

    下载地址:https://github.com/handcircus/Unity-Resource-Checker

    使用:Unity导航菜单栏中选择 Windows -> Resource Checker ,点击即可

    二、UnityAssetCleaner 

    超级diao炸天的插件,强烈推荐使用,有三种清理资源的模式,更重要的是,它把assets下的资源删除后,

    自动将删除的文件备份一个package包,这样再也不用担心误删有用的资源啦,误删了,大不了再把package包导进来呗。

    代码:

      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

    下载地址:https://github.com/unity-cn/Tool-UnityAssetCleaner

    使用:Unity导航菜单栏中选择 Assets-> Delete Unused Assets

    三种模式,选择一个合适的,然后点击Delete,轻松搞定

  • 相关阅读:
    Linux常用操作命令大全
    判断系统,是否是移动端
    一款兼容小程序和web端的框架 Kbone-API
    defer 和 async的区别
    快应用多次弹出添加到桌面的bug
    js判断一个元素是否在数组中
    css 画太极
    css3锯齿
    js 获取屏幕宽度
    js 判断div距离浏览器顶部或者底部的距离
  • 原文地址:https://www.cnblogs.com/Jason-c/p/7526326.html
Copyright © 2020-2023  润新知