Resource Checker (FREE) - List Texture/Material/Mesh Memory use in scene

Discussion in 'Assets and Asset Store' started by SimonOliver, Apr 13, 2012.

  1. SimonOliver

    SimonOliver

    Member

    Joined:
    Jul 16, 2007
    Messages:
    6
    [​IMG]

    Hey,

    I've been trying to find the best way to list currently used textures in a given scene, and the amount of memory they consume (profiler not providing a breakdown of texture memory). Also wanted to see where active textures are being used, by which GameObjects, which materials and the number of materials/meshes currently used in the scene.

    I couldn't find a workflow that best suits this, so knocked up a quick Editor extension that might help if you are looking to do something similar. You can download from here:

    https://github.com/handcircus/Unity-Resource-Checker

    Newish to Unity so there might be a really obvious way of doing this already that I'm not aware of. Anyway, its public domain, so do whatever you like with it, hope its of use to some of you :)

    ------

    Resource checker is designed to help bring visibility to resource use in your scenes (ie what assets are using up memory,
    which meshes are a bit too detailed, where are my materials and textures being used).

    It should also be useful to check for redundant materials, textures you forget you're using, textures that can be compressed or reduced in size.

    To use, just create an "Editor" folder within "Assets" in your project if you don't already have one, and drop ResourceChecker.cs in there.

    In Unity you'll see a new option under "Window" -> "Resource Checker"

    To use, once the window is open, just click 'Refresh' and it will list all active textures, materials and meshes in the scene

    Textures
    --------

    - Textures are listed in descending memory size
    - Click the texture name to open the asset in the project window
    - The size of the texture, compression type and dimensions are show
    - Click the 'X Mat' button to select all materials that use this texture in the scene
    - Click the 'X GO' to select all game objects in the scene that use this texture

    Materials
    ---------

    - Click the material name to open the material asset in the project window
    - Click the 'X GO' to select all game objects in the scene that use this material

    Meshes
    ------
    - Meshes are listed in descending vertex count
    - Click the mesh name to open the mesh in the project window
    - Click the 'X GO' to select all game objects in the scene that use this mesh

    Its probably got a bunch of bugs and weird issues - feel free to help improve, fix up!
     
  2. yuriythebest

    yuriythebest

    Member

    Joined:
    Nov 21, 2009
    Messages:
    946
    wow dude! this is epic- while something similar exists in the Profiler this looks amazing
     
  3. hima

    hima

    New Member

    Joined:
    Oct 1, 2010
    Messages:
    179
    This is going to be very useful. Thank you for making it free and opensource!
     
  4. Wild Factor

    Wild Factor

    Member

    Joined:
    Oct 11, 2010
    Messages:
    512
    Thanks It's probably very useffull for non-pro user.
     
  5. SimonOliver

    SimonOliver

    Member

    Joined:
    Jul 16, 2007
    Messages:
    6
    Cool, glad its of use! Will try to get up to the store soon too.

    In terms of profiler, I couldn't see any breakdown of memory use by asset, just a total of all textures, all meshes. Is there an option in the profiler that lets you dig deeper to see how that chunk of memory is split up?
     
  6. Lars Steenhoff

    Lars Steenhoff

    Member

    Joined:
    Aug 7, 2007
    Messages:
    874
    Really nice plugin!

    I'm using it now to reduce my texture settings from 1024 to 512, do you have a way to sort by texture size and to select all textures at once to mass change them?

    Thanks
     
  7. SimonOliver

    SimonOliver

    Member

    Joined:
    Jul 16, 2007
    Messages:
    6
    At the moment it sorts by size of Texture in memory (so if you are using similar compression on most assets, this will be the same result as sorting by texture size, except for cubemaps). I can definitely add a sort alphabetically or just by texture size easily enough. Multi-selection should be easy enough to do too, so do you mean ctrl-select for multi-selection, or a "select all" button or both?
     
  8. Lars Steenhoff

    Lars Steenhoff

    Member

    Joined:
    Aug 7, 2007
    Messages:
    874
    I think control select, and shift select range will suffice, sort by texture properties would be nice, ( 256, 512,1024 etc )
     
  9. SimonOliver

    SimonOliver

    Member

    Joined:
    Jul 16, 2007
    Messages:
    6
    Just added Ctrl select, and a select all button at the bottom. Also list mip levels and some size calculation bugs fixed
     
  10. yuriythebest

    yuriythebest

    Member

    Joined:
    Nov 21, 2009
    Messages:
    946
    I made a small hack/modification- now this will update every second.. sorta.. I think :)
    (there is probably a MUCH prettier way of doing this)
    Thank you again handcircus !!

    Code (csharp):
    1. // Resource Checker
    2. // (c) 2012 Simon Oliver / HandCircus / hello@handcircus.com
    3. // Public domain, do with whatever you like, commercial or not
    4. // This comes with no warranty, use at your own risk!
    5. // https://github.com/handcircus/Unity-Resource-Checker
    6.  
    7. using UnityEngine;
    8. using UnityEditor;
    9. using System.Collections.Generic;
    10.  
    11.  
    12. public class TextureDetails
    13. {
    14.     public bool isCubeMap;
    15.     public int memSizeKB;
    16.     public Texture texture;
    17.     public TextureFormat format;
    18.     public int mipMapCount;
    19.     public List<Object> FoundInMaterials=new List<Object>();
    20.     public List<Object> FoundInRenderers=new List<Object>();
    21.     public TextureDetails()
    22.     {
    23.  
    24.     }
    25. };
    26.  
    27. public class MaterialDetails
    28. {
    29.  
    30.     public Material material;
    31.  
    32.     public List<Renderer> FoundInRenderers=new List<Renderer>();
    33.  
    34.     public MaterialDetails()
    35.     {
    36.  
    37.     }
    38. };
    39.  
    40. public class MeshDetails
    41. {
    42.  
    43.     public Mesh mesh;
    44.  
    45.     public List<MeshFilter> FoundInMeshFilters=new List<MeshFilter>();
    46.  
    47.     public MeshDetails()
    48.     {
    49.  
    50.     }
    51. };
    52.  
    53. public  class ResourceChecker : EditorWindow {
    54.  
    55.     float timer=0;
    56.     string[] inspectToolbarStrings = {"Textures", "Materials","Meshes"};
    57.  
    58.     enum InspectType
    59.     {
    60.         Textures,Materials,Meshes
    61.     };
    62.  
    63.     InspectType ActiveInspectType=InspectType.Textures;
    64.  
    65.     float ThumbnailWidth=40;
    66.     float ThumbnailHeight=40;
    67.  
    68.     static List<TextureDetails> ActiveTextures=new List<TextureDetails>();
    69.     static List<MaterialDetails> ActiveMaterials=new List<MaterialDetails>();
    70.     static List<MeshDetails> ActiveMeshDetails=new List<MeshDetails>();
    71.  
    72.     static Vector2 textureListScrollPos=new Vector2(0,0);
    73.     static Vector2 materialListScrollPos=new Vector2(0,0);
    74.     static Vector2 meshListScrollPos=new Vector2(0,0);
    75.  
    76.     static int TotalTextureMemory=0;
    77.     static int TotalMeshVertices=0;
    78.  
    79.     bool ctrlPressed=false;
    80.  
    81.     static int MinWidth=455;
    82.      static ResourceChecker window;
    83.     [MenuItem ("Window/Resource Checker")]
    84.     static void Init ()
    85.     {  
    86.         TotalTextureMemory=0;
    87.         TotalMeshVertices=0;
    88.         textureListScrollPos=new Vector2(0,0);
    89.         materialListScrollPos=new Vector2(0,0);
    90.         meshListScrollPos=new Vector2(0,0);
    91.         ActiveTextures=new List<TextureDetails>();
    92.         ActiveMaterials=new List<MaterialDetails>();
    93.         ActiveMeshDetails=new List<MeshDetails>();
    94.         window = (ResourceChecker) EditorWindow.GetWindow (typeof (ResourceChecker));
    95.         window.CheckResources();
    96.         window.minSize=new Vector2(MinWidth,300);
    97.     }
    98.    
    99.     void Update()
    100.     {
    101.         timer+=Time.deltaTime;
    102.         if(timer>1)
    103.         {
    104.             Init ();
    105.             timer=0;
    106.         }
    107.        
    108.     }
    109.    
    110.     void OnGUI ()
    111.     {
    112.         if (GUILayout.Button("Refresh")) CheckResources();
    113.         GUILayout.BeginHorizontal();
    114.         GUILayout.Label("Materials "+ActiveMaterials.Count);
    115.         GUILayout.Label("Textures "+ActiveTextures.Count+" - "+FormatSizeString(TotalTextureMemory));
    116.         GUILayout.Label("Meshes "+ActiveMeshDetails.Count+" - "+TotalMeshVertices+" verts");
    117.         GUILayout.EndHorizontal();
    118.         ActiveInspectType=(InspectType)GUILayout.Toolbar((int)ActiveInspectType,inspectToolbarStrings);
    119.  
    120.         ctrlPressed=Event.current.control || Event.current.command;
    121.  
    122.         switch (ActiveInspectType)
    123.         {
    124.             case InspectType.Textures:
    125.                 ListTextures();
    126.                 break;
    127.             case InspectType.Materials:
    128.                 ListMaterials();
    129.                 break;
    130.             case InspectType.Meshes:
    131.                 ListMeshes();
    132.                 break
    133.  
    134.  
    135.         }
    136.     }
    137.  
    138.  
    139.     int GetBitsPerPixel(TextureFormat format)
    140.     {
    141.         switch (format)
    142.         {
    143.             case TextureFormat.Alpha8: //    Alpha-only texture format.
    144.                 return 8;
    145.             case TextureFormat.ARGB4444: //  A 16 bits/pixel texture format. Texture stores color with an alpha channel.
    146.                 return 16;
    147.             case TextureFormat.RGB24:   // A color texture format.
    148.                 return 24;
    149.             case TextureFormat.RGBA32:  //Color with an alpha channel texture format.
    150.                 return 32;
    151.             case TextureFormat.ARGB32:  //Color with an alpha channel texture format.
    152.                 return 32;
    153.             case TextureFormat.RGB565:  //   A 16 bit color texture format.
    154.                 return 16;
    155.             case TextureFormat.DXT1:    // Compressed color texture format.
    156.                 return 4;
    157.             case TextureFormat.DXT5:    // Compressed color with alpha channel texture format.
    158.                 return 8;
    159.             /*
    160.             case TextureFormat.WiiI4:   // Wii texture format.
    161.             case TextureFormat.WiiI8:   // Wii texture format. Intensity 8 bit.
    162.             case TextureFormat.WiiIA4:  // Wii texture format. Intensity + Alpha 8 bit (4 + 4).
    163.             case TextureFormat.WiiIA8:  // Wii texture format. Intensity + Alpha 16 bit (8 + 8).
    164.             case TextureFormat.WiiRGB565:   // Wii texture format. RGB 16 bit (565).
    165.             case TextureFormat.WiiRGB5A3:   // Wii texture format. RGBA 16 bit (4443).
    166.             case TextureFormat.WiiRGBA8:    // Wii texture format. RGBA 32 bit (8888).
    167.             case TextureFormat.WiiCMPR: //   Compressed Wii texture format. 4 bits/texel, ~RGB8A1 (Outline alpha is not currently supported).
    168.                 return 0;  //Not supported yet
    169.             */
    170.             case TextureFormat.PVRTC_RGB2://     PowerVR (iOS) 2 bits/pixel compressed color texture format.
    171.                 return 2;
    172.             case TextureFormat.PVRTC_RGBA2://    PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format
    173.                 return 2;
    174.             case TextureFormat.PVRTC_RGB4://     PowerVR (iOS) 4 bits/pixel compressed color texture format.
    175.                 return 4;
    176.             case TextureFormat.PVRTC_RGBA4://    PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format
    177.                 return 4;
    178.             case TextureFormat.ETC_RGB4://   ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.
    179.                 return 4;
    180.             case TextureFormat.ATC_RGB4://   ATC (ATITC) 4 bits/pixel compressed RGB texture format.
    181.                 return 4;
    182.             case TextureFormat.ATC_RGBA8://  ATC (ATITC) 8 bits/pixel compressed RGB texture format.
    183.                 return 8;
    184.             case TextureFormat.BGRA32://     Format returned by iPhone camera
    185.                 return 32;
    186.             case TextureFormat.ATF_RGB_DXT1://   Flash-specific RGB DXT1 compressed color texture format.
    187.             case TextureFormat.ATF_RGBA_JPG://   Flash-specific RGBA JPG-compressed color texture format.
    188.             case TextureFormat.ATF_RGB_JPG://    Flash-specific RGB JPG-compressed color texture format.
    189.                 return 0; //Not supported yet
    190.         }
    191.         return 0;
    192.     }
    193.  
    194.     int CalculateTextureSizeBytes(Texture tTexture)
    195.     {
    196.  
    197.         int tWidth=tTexture.width;
    198.         int tHeight=tTexture.height;
    199.         if (tTexture is Texture2D)
    200.         {
    201.             Texture2D tTex2D=tTexture as Texture2D;
    202.             int bitsPerPixel=GetBitsPerPixel(tTex2D.format);
    203.             int mipMapCount=tTex2D.mipmapCount;
    204.             int mipLevel=1;
    205.             int tSize=0;
    206.             while (mipLevel<=mipMapCount)
    207.             {
    208.                 tSize+=tWidth*tHeight*bitsPerPixel/8;
    209.                 tWidth=tWidth/2;
    210.                 tHeight=tHeight/2;
    211.                 mipLevel++;
    212.             }
    213.             return tSize;
    214.         }
    215.  
    216.         if (tTexture is Cubemap)
    217.         {
    218.             Cubemap tCubemap=tTexture as Cubemap;
    219.             int bitsPerPixel=GetBitsPerPixel(tCubemap.format);
    220.             return tWidth*tHeight*6*bitsPerPixel/8;
    221.         }
    222.         return 0;
    223.     }
    224.  
    225.  
    226.     void SelectObject(Object selectedObject,bool append)
    227.     {
    228.         if (append)
    229.         {
    230.             List<Object> currentSelection=new List<Object>(Selection.objects);
    231.             // Allow toggle selection
    232.             if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject);
    233.             else currentSelection.Add(selectedObject);
    234.  
    235.             Selection.objects=currentSelection.ToArray();
    236.         }
    237.         else Selection.activeObject=selectedObject;
    238.     }
    239.  
    240.     void SelectObjects(List<Object> selectedObjects,bool append)
    241.     {
    242.         if (append)
    243.         {
    244.             List<Object> currentSelection=new List<Object>(Selection.objects);
    245.             currentSelection.AddRange(selectedObjects);
    246.             Selection.objects=currentSelection.ToArray();
    247.         }
    248.         else Selection.objects=selectedObjects.ToArray();
    249.     }
    250.  
    251.     void ListTextures()
    252.     {
    253.         textureListScrollPos = EditorGUILayout.BeginScrollView(textureListScrollPos);
    254.         try
    255.         {
    256.         foreach (TextureDetails tDetails in ActiveTextures)
    257.         {          
    258.  
    259.             GUILayout.BeginHorizontal ();
    260.             GUILayout.Box(tDetails.texture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
    261.            
    262.             if(tDetails.texture==null)
    263.                 Init();
    264.            
    265.             if(tDetails!=null)
    266.             try
    267.             {  
    268.                 if(tDetails.texture!=null)
    269.                 if(GUILayout.Button(tDetails.texture.name,GUILayout.Width(150)))
    270.                 {
    271.                     SelectObject(tDetails.texture,ctrlPressed);
    272.                
    273.                
    274.                     string sizeLabel=""+tDetails.texture.width+"x"+tDetails.texture.height;
    275.                     if (tDetails.isCubeMap) sizeLabel+="x6";
    276.                     sizeLabel+=" - "+tDetails.mipMapCount+"mip";
    277.                     sizeLabel+="\n"+FormatSizeString(tDetails.memSizeKB)+" - "+tDetails.format+"";
    278.        
    279.                     GUILayout.Label (sizeLabel,GUILayout.Width(120));
    280.                 }
    281.                 if(GUILayout.Button(tDetails.FoundInMaterials.Count+" Mat",GUILayout.Width(50)))
    282.                 {
    283.                     SelectObjects(tDetails.FoundInMaterials,ctrlPressed);
    284.                 }
    285.    
    286.                 if(GUILayout.Button(tDetails.FoundInRenderers.Count+" GO",GUILayout.Width(50)))
    287.                 {
    288.                     List<Object> FoundObjects=new List<Object>();
    289.                     foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
    290.                     SelectObjects(FoundObjects,ctrlPressed);
    291.                 }
    292.    
    293.                 GUILayout.EndHorizontal()
    294.             }
    295.             catch
    296.             {
    297.                
    298.             }
    299.         }
    300.         if (ActiveTextures.Count>0)
    301.         {
    302.             GUILayout.BeginHorizontal ();
    303.             GUILayout.Box(" ",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));
    304.  
    305.             if(GUILayout.Button("Select All",GUILayout.Width(150)))
    306.             {
    307.                 List<Object> AllTextures=new List<Object>();
    308.                 foreach (TextureDetails tDetails in ActiveTextures) AllTextures.Add(tDetails.texture);
    309.                 SelectObjects(AllTextures,ctrlPressed);
    310.             }
    311.             EditorGUILayout.EndHorizontal();
    312.            
    313.         }
    314.                 }
    315.         catch{}
    316.    
    317.     }
    318.  
    319.     void ListMaterials()
    320.     {
    321.         materialListScrollPos = EditorGUILayout.BeginScrollView(materialListScrollPos);
    322.  
    323.         foreach (MaterialDetails tDetails in ActiveMaterials)
    324.         {          
    325.             if (tDetails.material!=null)
    326.             {
    327.                 GUILayout.BeginHorizontal ();
    328.  
    329.                 if (tDetails.material.mainTexture!=null) GUILayout.Box(tDetails.material.mainTexture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
    330.                 else   
    331.                 {
    332.                     GUILayout.Box("n/a",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));
    333.                 }
    334.  
    335.                 if(GUILayout.Button(tDetails.material.name,GUILayout.Width(150)))
    336.                 {;
    337.                     SelectObject(tDetails.material,ctrlPressed);
    338.                 }
    339.  
    340.                 if(GUILayout.Button(tDetails.FoundInRenderers.Count+" GO",GUILayout.Width(50)))
    341.                 {
    342.                     List<Object> FoundObjects=new List<Object>();
    343.                     foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
    344.                     SelectObjects(FoundObjects,ctrlPressed);
    345.                 }
    346.  
    347.  
    348.                 GUILayout.EndHorizontal()
    349.             }
    350.         }
    351.         EditorGUILayout.EndScrollView();       
    352.     }
    353.  
    354.     void ListMeshes()
    355.     {
    356.         meshListScrollPos = EditorGUILayout.BeginScrollView(meshListScrollPos);
    357.  
    358.         foreach (MeshDetails tDetails in ActiveMeshDetails)
    359.         {          
    360.             if (tDetails.mesh!=null)
    361.             {
    362.                 GUILayout.BeginHorizontal ();
    363.                 /*
    364.                 if (tDetails.material.mainTexture!=null) GUILayout.Box(tDetails.material.mainTexture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
    365.                 else   
    366.                 {
    367.                     GUILayout.Box("n/a",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));
    368.                 }
    369.                 */
    370.  
    371.                 if(GUILayout.Button(tDetails.mesh.name,GUILayout.Width(150)))
    372.                 {
    373.                     SelectObject(tDetails.mesh,ctrlPressed);
    374.                 }
    375.                 string sizeLabel=""+tDetails.mesh.vertexCount+" vert";
    376.  
    377.                 GUILayout.Label (sizeLabel,GUILayout.Width(100));
    378.  
    379.  
    380.                 if(GUILayout.Button(tDetails.FoundInMeshFilters.Count+" GO",GUILayout.Width(50)))
    381.                 {
    382.                     List<Object> FoundObjects=new List<Object>();
    383.                     foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters) FoundObjects.Add(meshFilter.gameObject);
    384.                     SelectObjects(FoundObjects,ctrlPressed);
    385.                 }
    386.  
    387.  
    388.                 GUILayout.EndHorizontal()
    389.             }
    390.         }
    391.         EditorGUILayout.EndScrollView();       
    392.     }
    393.  
    394.     string FormatSizeString(int memSizeKB)
    395.     {
    396.         if (memSizeKB<1024) return ""+memSizeKB+"k";
    397.         else
    398.         {
    399.             float memSizeMB=((float)memSizeKB)/1024.0f;
    400.             return memSizeMB.ToString("0.00")+"Mb";
    401.         }
    402.     }
    403.  
    404.  
    405.     TextureDetails FindTextureDetails(Texture tTexture)
    406.     {
    407.         foreach (TextureDetails tTextureDetails in ActiveTextures)
    408.         {
    409.             if (tTextureDetails.texture==tTexture) return tTextureDetails;
    410.         }
    411.         return null;
    412.  
    413.     }
    414.  
    415.     MaterialDetails FindMaterialDetails(Material tMaterial)
    416.     {
    417.         foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
    418.         {
    419.             if (tMaterialDetails.material==tMaterial) return tMaterialDetails;
    420.         }
    421.         return null;
    422.  
    423.     }
    424.  
    425.     MeshDetails FindMeshDetails(Mesh tMesh)
    426.     {
    427.         foreach (MeshDetails tMeshDetails in ActiveMeshDetails)
    428.         {
    429.             if (tMeshDetails.mesh==tMesh) return tMeshDetails;
    430.         }
    431.         return null;
    432.  
    433.     }
    434.  
    435.  
    436.     void CheckResources()
    437.     {
    438.         ActiveTextures.Clear();
    439.         ActiveMaterials.Clear();
    440.         ActiveMeshDetails.Clear();
    441.  
    442.         Renderer[] renderers = (Renderer[]) FindObjectsOfType(typeof(Renderer));
    443.         //Debug.Log("Total renderers "+renderers.Length);
    444.         foreach (Renderer renderer in renderers)
    445.         {
    446.             //Debug.Log("Renderer is "+renderer.name);
    447.             foreach (Material material in renderer.sharedMaterials)
    448.             {
    449.  
    450.                 MaterialDetails tMaterialDetails=FindMaterialDetails(material);
    451.                 if (tMaterialDetails==null)
    452.                 {
    453.                     tMaterialDetails=new MaterialDetails();
    454.                     tMaterialDetails.material=material;
    455.                     ActiveMaterials.Add(tMaterialDetails);
    456.                 }
    457.                 tMaterialDetails.FoundInRenderers.Add(renderer);
    458.             }
    459.         }
    460.  
    461.         foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
    462.         {
    463.             Material tMaterial=tMaterialDetails.material;
    464.             foreach (Object obj in EditorUtility.CollectDependencies(new UnityEngine.Object[] {tMaterial}))
    465.             {
    466.                 if (obj is Texture)
    467.                 {
    468.                     Texture tTexture=obj as Texture;
    469.                     TextureDetails tTextureDetails=FindTextureDetails(tTexture);
    470.                     if (tTextureDetails==null)
    471.                     {
    472.                         tTextureDetails=new TextureDetails();
    473.                         tTextureDetails.texture=tTexture;
    474.                         tTextureDetails.isCubeMap=tTexture is Cubemap;
    475.  
    476.                         int memSize=CalculateTextureSizeBytes(tTexture);
    477.  
    478.                         tTextureDetails.memSizeKB=memSize/1024;
    479.                         TextureFormat tFormat=TextureFormat.RGBA32;
    480.                         int tMipMapCount=1;
    481.                         if (tTexture is Texture2D)
    482.                         {
    483.                             tFormat=(tTexture as Texture2D).format;
    484.                             tMipMapCount=(tTexture as Texture2D).mipmapCount;
    485.                         }
    486.                         if (tTexture is Cubemap)
    487.                         {
    488.                             tFormat=(tTexture as Cubemap).format;
    489.                         }
    490.  
    491.                         tTextureDetails.format=tFormat;
    492.                         tTextureDetails.mipMapCount=tMipMapCount;
    493.                         ActiveTextures.Add(tTextureDetails);
    494.                     }
    495.                     tTextureDetails.FoundInMaterials.Add(tMaterial);
    496.                     foreach (Renderer renderer in tMaterialDetails.FoundInRenderers)
    497.                     {
    498.                         if (!tTextureDetails.FoundInRenderers.Contains( renderer)) tTextureDetails.FoundInRenderers.Add(renderer);
    499.                     }
    500.                 }
    501.             }
    502.         }
    503.  
    504.  
    505.         MeshFilter[] meshFilters = (MeshFilter[]) FindObjectsOfType(typeof(MeshFilter));
    506.  
    507.         foreach (MeshFilter tMeshFilter in meshFilters)
    508.         {
    509.             Mesh tMesh=tMeshFilter.sharedMesh;
    510.             if (tMesh!=null)
    511.             {
    512.                 MeshDetails tMeshDetails=FindMeshDetails(tMesh);
    513.                 if (tMeshDetails==null)
    514.                 {
    515.                     tMeshDetails=new MeshDetails();
    516.                     tMeshDetails.mesh=tMesh;
    517.                     ActiveMeshDetails.Add(tMeshDetails);
    518.                 }
    519.                 tMeshDetails.FoundInMeshFilters.Add(tMeshFilter);
    520.             }
    521.         }
    522.  
    523.  
    524.         TotalTextureMemory=0;
    525.         foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory+=tTextureDetails.memSizeKB;
    526.  
    527.         TotalMeshVertices=0;
    528.         foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices+=tMeshDetails.mesh.vertexCount;
    529.  
    530.         // Sort by size, descending
    531.         ActiveTextures.Sort(delegate(TextureDetails details1, TextureDetails details2) {return details2.memSizeKB-details1.memSizeKB;});
    532.         ActiveMeshDetails.Sort(delegate(MeshDetails details1, MeshDetails details2) {return details2.mesh.vertexCount-details1.mesh.vertexCount;});
    533.  
    534.     }
    535.  
    536.  
    537. }
     
    Last edited: May 3, 2012
  11. rextr09

    rextr09

    Member

    Joined:
    Dec 22, 2011
    Messages:
    400
    Thanks for this great tool, it's so useful.
    I have a question about texture sizes. Even though I set the "Texture Quality" = "Half Res" in Quality settings, the tool still displays the full resolution. Is this normal?
     
  12. yuriythebest

    yuriythebest

    Member

    Joined:
    Nov 21, 2009
    Messages:
    946
    I think this is the case because in the Unity Editor they are fully loaded into memory.. I think, while when in standalone they might not be. That or the script just looks at the original texture size.

    This script is amazing though, especially for mobile development, where an accidentally loaded texture atlas can be the difference between your app working and not
     
  13. rextr09

    rextr09

    Member

    Joined:
    Dec 22, 2011
    Messages:
    400
    OK, thanks...
    And yes this is amazing.... using this tool I have spot and reduced all my 1024*1024 textures to 256*256 without much affecting overall quality.
     
  14. Rush Rage Games

    Rush Rage Games

    Member

    Joined:
    Sep 9, 2010
    Messages:
    1,999
  15. gmayer

    gmayer

    New Member

    Joined:
    May 15, 2012
    Messages:
    4
    Amazing work man!
    Thanks!!
     
  16. AShim.3D

    AShim.3D

    Member

    Joined:
    Jul 13, 2012
    Messages:
    26
    Add support SkinnedMeshRenderer, see on GitHub
     
  17. 3ddf

    3ddf

    Member

    Joined:
    Mar 18, 2010
    Messages:
    6
    Really useful, thanks!
     
  18. moproductions

    moproductions

    Member

    Joined:
    Sep 28, 2010
    Messages:
    68
    Quick question for the thread. When loading up a scene directly the Profiler says I'm using 1068 textures using 53.2 MB.
    When loading the same scene from another scene, the Profiler says I'm using 1071 textures using 70.4 MB.

    I used this tool (which is FANTASTIC, btw) in both cases, but the tool said that I was using the exact same amount of resources (textures, materials, objects).

    I think the tool is working properly, but that means that there's some (large) textures still around somewhere eating up memory.
    Is there a way that I can track down those 3 extra textures lurking around in memory that the tool isn't catching?

    Thanks
    -Mo
     
  19. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    11,341
    Freaking amazing utility. Can't believe I never used it before. Now it is an integral part of our pipeline.
     
  20. joshimoo

    joshimoo

    Member

    Joined:
    Jun 23, 2011
    Messages:
    266
    Looks very good, wish the profiler had a texture breakdown like this =)
     
  21. Lars Steenhoff

    Lars Steenhoff

    Member

    Joined:
    Aug 7, 2007
    Messages:
    874
    This is one of the must have tools that I use daily to optimise my game, it would be nice to see an asset store version too.
     
  22. hike1

    hike1

    Member

    Joined:
    Sep 6, 2009
    Messages:
    259
    Thanks!
     
  23. pedroathumanspot

    pedroathumanspot

    New Member

    Joined:
    Oct 30, 2012
    Messages:
    9
    Hi!

    Bummer. It seems I can't get this script to work. :neutral: I already copied the ResourceChecker.cs script to the Assets/Editor folder - and it loads right - but don't display any texture, or material, or mesh. It makes some sense because I'm using NGUI - and all my textures are loaded at runtime, to save memory - but is quite strange that even when I'm hitting 'Refresh' on runtime it still gives me nothing. (I mean, the NGUI UITexture has some Texture2D encapsulated, right?)

    Even so, I guess I'm going to try and port ResourceChecker to NGUI. By any chance, is any work underway to do this?

    Cheers.
     
  24. rextr09

    rextr09

    Member

    Joined:
    Dec 22, 2011
    Messages:
    400
    Yes, I think this is not compatible with NGUI.
     
  25. sparrow

    sparrow

    Member

    Joined:
    May 6, 2012
    Messages:
    14
    Thank you, something like this is a must have in the profiler. This was incredibly helpful
     
  26. Sisso

    Sisso

    Member

    Joined:
    Sep 29, 2009
    Messages:
    163
    You can see what is used by ngui if you change ResourceChecker search in all loaded resources instead scene objects. Replace

    Code (csharp):
    By

    Code (csharp):
     
  27. stevesan

    stevesan

    Member

    Joined:
    Aug 14, 2011
    Messages:
    44
    How about lightmaps? Probably pretty easy to add :)
     
  28. bchevalier

    bchevalier

    Member

    Joined:
    Feb 13, 2013
    Messages:
    42
    Hi guys,

    this tool is awesome ! it seems to work properly on my side, but I'm having warnings like that one whenever I refresh :



    Any ideas ? I'm using Unity 4.3 pro

    Thanks !
    ben
     
  29. larku

    larku

    Member

    Joined:
    Mar 14, 2013
    Messages:
    31
    Yep on line 455 add an extra check so it reads like:

    Code (csharp):
    1. if (tMaterial != null && tMaterial.mainTexture != null && !dependencies.Contains(tMaterial.mainTexture))
     
    Last edited: Sep 20, 2014