unity3d 删除无用资源_unity3d 去掉无用资源 - CSDN
  • Unity Global Support部门制作了一些实用的小工具免费供大家使用,前面已经分享过了处理资源的AssetGraph,今天继续为大家推荐用于批量清理资源的小工具:Asset Cleaner。 Unity Global Support部门主要负责对使用...
    Unity Global Support部门制作了一些实用的小工具免费供大家使用,前面已经分享过了处理资源的AssetGraph,今天继续为大家推荐用于批量清理资源的小工具:Asset Cleaner。
    Unity Global Support部门主要负责对使用Unity引擎的企业级VIP客户提供技术支持,大中华区已实现全面覆盖,目前包括腾讯,网易,巨人,完美世界等公司已属于Unity的企业级VIP客户。 Asset Cleaner主要用于查找并删除没有被引用的资源,简单易用,且具有高度可扩展性。

    项目背景:
    在Unity项目中,我们习惯将所有的资源统称为Asset。Asset一般存放在Assets目录及其子目录。随着项目的研发进度,Asset数量也会爆发式地增长,资源管理面临很大的挑战。如何查找并区分有效和无效的资源,是很多项目管理者非常重视的事情。本文介绍的这个工具可以自动分析查找项目中未使用到的资源,在选择删除的时候还可以将这些文件打包备份,确保资源的安全性、提高项目管理的效率。

    实现原理:
    该工程只有四个CS文件,需存放在Editor目录下。



    FindUnusedAssets是这个工具的主要入口,实现了编辑器的扩展菜单及其内部调用。
    AssetCollector是总的工具类,用来收集所有的asset文件
    ClassReferenceCollection用来收集所有的.cs脚本文件。
    ShaderReferenceCollection用来收集所有的Shader文件。

    AssetCollector
    AssetCollector实现了这个工具的核心代码,点击菜单时会调用定义在它内部的Collection函数。AssetCollector中声明了两个变量,useCodeStrip和saveEditorExtensions。useCodeStrip用来控制要不要删除未使用的脚本文件,saveEditorExtensions用来控制检测资源是否被Editor脚本引用。工具中提供了三个菜单项,分别是only resource、unused by editor、unused by game。这三个菜单项执行的代码就是通过设置useCodeStrip和saveEditorExtensions为不同的值来控制过滤的方式。

    [C#] 纯文本查看 复制代码
    ?
    public bool useCodeStrip = true;
    public bool saveEditorExtensions = true;


    资源搜集

    Collection函数内实现了各种类型资源文件的搜索过滤。
    -        Directory.GetFiles()获取“Asset”目录及其子目录下所有相关资源的名字,通过Linq语法进行过滤,获取需要的文件类型。
    -        
    [C#] 纯文本查看 复制代码
    ?
    var files = Directory.GetFiles
    (
        "Assets", "*.*", SearchOption.AllDirectories
    )
            .Where (item => Path.GetExtension (item) != ".meta")
            .Where (item => Path.GetExtension (item) != ".js")
            .Where (item => Path.GetExtension (item) != ".dll")
            .Where (item => Regex.IsMatch (item, "[\\/\\\\]Gizmos[\\/\\\\]") == false)
            .Where (item => Regex.IsMatch (item, "[\\/\\\\]Plugins[\\/\\\\]Android[\\/\\\\]") == false)
    .Where (item => Regex.IsMatch (item, "[\\/\\\\]Plugins[\\/\\\\]iOS[\\/\\\\]") == false)
            .Where (item => Regex.IsMatch (item, "[\\/\\\\]Resources[\\/\\\\]") == false);

    依赖关系获取
    -        通过AssetDatabase.GetDependencies获取当前有效的场景文件及场景依赖文件。

    [C#] 纯文本查看 复制代码
    ?
    var scenes = EditorBuildSettings.scenes
                                    .Where (item => item.enabled == true)
                                            .Select (item => item.path)
                                            .ToArray ();
    foreach (var path in AssetDatabase.GetDependencies (scenes))
    {
    //剔除被依赖的文件
    }

    使用介绍:

    首先我们要保证当前工程中存在有效的场景文件,因为Asset资源的有效性依赖于是否被场景引用。



    使用时需要找到这个菜单项Assets->Delete Unused Assets,如下图所示。



    Delete Unused Assets下有三个选项,分别是删除未使用的资源文件(only resource),删除编辑器未使用的Asset(unused by editor)和删除游戏未使用的Asset(unused by game)。

    使用方法:
    在开始使用该工具时,要保证有效的EditorBuildSettings.scenes
    选择Delete Unused Assets下“only resource”选项,弹出对应的删除列表。如下图所示:


    显示在删除列表中文件,单击“Delete”,列表中的文件从项目中移除,工具会把这些文件作为一个UnityPackage导出到“../ BackupUnusedAssets/”。这个包作为被删除文件的备份,如果后期发现有资源丢失,可以从这个包内找到对应的资源文件重新导入。



    上面简单介绍了Asset Cleaner工程的工作原理及使用方式。在实战中,我们可以根据需求自定义查找文件的格式。
    关于该工具如有任何疑问,可以评论留言提问。

    下载地址:https://github.com/unity-cn/Tool-UnityAssetCleaner
    展开全文
  • Unity3d删除无用的美术资源 这个插件是我在国外网站逛论坛发现的,试用了一下非常好用,是一个轻量级的插件就一个类。开发中尤其是和美术合作的时候,可能你会发现Project视图中有很多没有用到的...


    Unity3d删除无用的美术资源




    这个插件是我在国外网站逛论坛发现的,试用了一下非常好用,是一个轻量级的插件就一个类。开发中尤其是和美术合作的时候,可能你会发现Project视图中有很多没有用到的资源,但是你又不敢删除,因为你不知道那些资源是没用到的,那些资源是用到的。这时候ResourceChecker可以帮上大忙。

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

    将ResourceChecker放在Project视图中的Editor文件夹中,如果没有该文件夹就创建一个。如下图所示,在Unity导航菜单栏中选择 Windows -> Resource Checker 即可呼出窗口。



    在Textures选项卡最下面点击 Select Al l 可在Project视图中展开目录结构,这时候你删除没有选中的文件就可以。。



    定位贴图、材质、网格。定位所有文件,总这这个小插件你值得拥有!

    代码如下:

    using UnityEngine;

    using UnityEditor;

    using System.Collections.Generic;





    public class TextureDetails

    {

    public bool isCubeMap;

    public int memSizeKB;

    publicTexture texture;

    publicTextureFormat format;

    public int mipMapCount;

    public List<Object> FoundInMaterials=new List<Object>();

    public List<Object> FoundInRenderers=new List<Object>();

    public TextureDetails()

    {



    }

    };



    public class MaterialDetails

    {



    publicMaterial material;



    public List<Renderer> FoundInRenderers=new List<Renderer>();



    public MaterialDetails()

    {



    }

    };



    public class MeshDetails

    {



    publicMesh mesh;



    public List<MeshFilter> FoundInMeshFilters=new List<MeshFilter>();

    public List<SkinnedMeshRenderer> FoundInSkinnedMeshRenderer=new List<SkinnedMeshRenderer>();



    public MeshDetails()

    {



    }

    };



    publicclass ResourceChecker : EditorWindow {





    string[] inspectToolbarStrings = {"Textures", "Materials","Meshes"} ;



    enum InspectType

    {

    Textures,Materials,Meshes

    } ;



    InspectType ActiveInspectType=InspectType.Textures;



    float ThumbnailWidth=40;

    float ThumbnailHeight=40;



    List<TextureDetails> ActiveTextures=new List<TextureDetails>();

    List<MaterialDetails> ActiveMaterials=new List<MaterialDetails>();

    List<MeshDetails> ActiveMeshDetails=new List<MeshDetails>();



    Vector2 textureListScrollPos=new Vector2(0,0);

    Vector2 materialListScrollPos=new Vector2(0,0);

    Vector2 meshListScrollPos=new Vector2(0,0);



    int TotalTextureMemory=0;

    int TotalMeshVertices=0;



    bool ctrlPressed=false;



    static int MinWidth=455;



        [MenuItem ("Window/Resource Checker")]

        static void Init ()

    {   

            ResourceChecker window = (ResourceChecker) EditorWindow.GetWindow (typeof (ResourceChecker));

    window.CheckResources();

    window.minSize=new Vector2(MinWidth,300);

        }



        void OnGUI ()

    {

    if (GUILayout.Button("Refresh")) CheckResources();

    GUILayout.BeginHorizontal();

    GUILayout.Label("Materials "+ActiveMaterials.Count);

    GUILayout.Label("Textures "+ActiveTextures.Count+" - "+FormatSizeString(TotalTextureMemory));

    GUILayout.Label("Meshes "+ActiveMeshDetails.Count+" - "+TotalMeshVertices+" verts");

    GUILayout.EndHorizontal();

    ActiveInspectType=(InspectType)GUILayout.Toolbar((int)ActiveInspectType,inspectToolbarStrings);



    ctrlPressed=Event.current.control || Event.current.command;



    switch (ActiveInspectType)

    {

    case InspectType.Textures:

    ListTextures();

    break;

    case InspectType.Materials:

    ListMaterials();

    break;

    case InspectType.Meshes:

    ListMeshes();

    break;





    }

    }





    int GetBitsPerPixel(TextureFormat format)

    {

    switch (format)

    {

    caseTextureFormat.Alpha8: // Alpha-only texture format.

    return 8;

    caseTextureFormat.ARGB4444: // A 16 bits/pixel texture format. Texture stores color with an alpha channel.

    return 16;

    caseTextureFormat.RGB24:// A color texture format.

    return 24;

    caseTextureFormat.RGBA32://Color with an alpha channel texture format.

    return 32;

    caseTextureFormat.ARGB32://Color with an alpha channel texture format.

    return 32;

    caseTextureFormat.RGB565:// A 16 bit color texture format.

    return 16;

    caseTextureFormat.DXT1:// Compressed color texture format.

    return 4;

    caseTextureFormat.DXT5:// Compressed color with alpha channel texture format.

    return 8;

    /*

    caseTextureFormat.WiiI4:// Wii texture format.

    caseTextureFormat.WiiI8:// Wii texture format. Intensity 8 bit.

    caseTextureFormat.WiiIA4:// Wii texture format. Intensity + Alpha 8 bit (4 + 4).

    caseTextureFormat.WiiIA8:// Wii texture format. Intensity + Alpha 16 bit (8 + 8).

    caseTextureFormat.WiiRGB565:// Wii texture format. RGB 16 bit (565).

    caseTextureFormat.WiiRGB5A3:// Wii texture format. RGBA 16 bit (4443).

    caseTextureFormat.WiiRGBA8:// Wii texture format. RGBA 32 bit (8888).

    caseTextureFormat.WiiCMPR:// Compressed Wii texture format. 4 bits/texel, ~RGB8A1 (Outline alpha is not currently supported).

    return0;  //Not supported yet

    */

    caseTextureFormat.PVRTC_RGB2:// PowerVR (iOS) 2 bits/pixel compressed color texture format.

    return 2;

    caseTextureFormat.PVRTC_RGBA2:// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format

    return 2;

    caseTextureFormat.PVRTC_RGB4:// PowerVR (iOS) 4 bits/pixel compressed color texture format.

    return 4;

    caseTextureFormat.PVRTC_RGBA4:// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format

    return 4;

    caseTextureFormat.ETC_RGB4:// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.

    return 4;

    caseTextureFormat.ATC_RGB4:// ATC (ATITC) 4 bits/pixel compressed RGB texture format.

    return 4;

    caseTextureFormat.ATC_RGBA8:// ATC (ATITC) 8 bits/pixel compressed RGB texture format.

    return 8;

    caseTextureFormat.BGRA32:// Format returned by iPhone camera

    return 32;

    caseTextureFormat.ATF_RGB_DXT1:// Flash-specific RGB DXT1 compressed color texture format.

    caseTextureFormat.ATF_RGBA_JPG:// Flash-specific RGBA JPG-compressed color texture format.

    caseTextureFormat.ATF_RGB_JPG:// Flash-specific RGB JPG-compressed color texture format.

    return0; //Not supported yet

    }

    return0;

    }



    int CalculateTextureSizeBytes(Texture tTexture)

    {



    int tWidth=tTexture.width;

    int tHeight=tTexture.height;

    if (tTexture is Texture2D)

    {

    Texture2D tTex2D=tTexture as Texture2D;

    int bitsPerPixel=GetBitsPerPixel(tTex2D.format);

    int mipMapCount=tTex2D.mipmapCount;

    int mipLevel=1;

    int tSize=0;

    while (mipLevel<=mipMapCount)

    {

    tSize+=tWidth*tHeight*bitsPerPixel/8;

    tWidth=tWidth/2;

    tHeight=tHeight/2;

    mipLevel++;

    }

    return tSize;

    }



    if (tTexture is Cubemap)

    {

    Cubemap tCubemap=tTexture as Cubemap;

    int bitsPerPixel=GetBitsPerPixel(tCubemap.format);

    return tWidth*tHeight*6*bitsPerPixel/8;

    }

    return0;

    }





    void SelectObject(Object selectedObject,bool append)

    {

    if (append)

    {

    List<Object> currentSelection=new List<Object>(Selection.objects);

    // Allow toggle selection

    if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject);

    else currentSelection.Add(selectedObject);



    Selection.objects=currentSelection.ToArray();

    }

    else Selection.activeObject=selectedObject;

    }



    void SelectObjects(List<Object> selectedObjects,bool append)

    {

    if (append)

    {

    List<Object> currentSelection=new List<Object>(Selection.objects);

    currentSelection.AddRange(selectedObjects);

    Selection.objects=currentSelection.ToArray();

    }

    else Selection.objects=selectedObjects.ToArray();

    }



    void ListTextures()

    {

    textureListScrollPos = EditorGUILayout.BeginScrollView(textureListScrollPos);



    foreach (TextureDetails tDetails in ActiveTextures)

    {



    GUILayout.BeginHorizontal ();

    GUILayout.Box(tDetails.texture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));



    if(GUILayout.Button(tDetails.texture.name,GUILayout.Width(150)))

    {

    SelectObject(tDetails.texture,ctrlPressed);

    }



    string sizeLabel=""+tDetails.texture.width+"x"+tDetails.texture.height;

    if (tDetails.isCubeMap) sizeLabel+="x6";

    sizeLabel+=" - "+tDetails.mipMapCount+"mip";

    sizeLabel+="\n"+FormatSizeString(tDetails.memSizeKB)+" - "+tDetails.format+"";



    GUILayout.Label (sizeLabel,GUILayout.Width(120));



    if(GUILayout.Button(tDetails.FoundInMaterials.Count+" Mat",GUILayout.Width(50)))

    {

    SelectObjects(tDetails.FoundInMaterials,ctrlPressed);

    }



    if(GUILayout.Button(tDetails.FoundInRenderers.Count+" GO",GUILayout.Width(50)))

    {

    List<Object> FoundObjects=new List<Object>();

    foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);

    SelectObjects(FoundObjects,ctrlPressed);

    }



    GUILayout.EndHorizontal();

    }

    if (ActiveTextures.Count>0)

    {

    GUILayout.BeginHorizontal ();

    GUILayout.Box(" ",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));



    if(GUILayout.Button("Select All",GUILayout.Width(150)))

    {

    List<Object> AllTextures=new List<Object>();

    foreach (TextureDetails tDetails in ActiveTextures) AllTextures.Add(tDetails.texture);

    SelectObjects(AllTextures,ctrlPressed);

    }

    EditorGUILayout.EndHorizontal();

    }

    EditorGUILayout.EndScrollView();

        }



    void ListMaterials()

    {

    materialListScrollPos = EditorGUILayout.BeginScrollView(materialListScrollPos);



    foreach (MaterialDetails tDetails in ActiveMaterials)

    {

    if (tDetails.material!=null)

    {

    GUILayout.BeginHorizontal ();



    if (tDetails.material.mainTexture!=null) GUILayout.Box(tDetails.material.mainTexture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));

    else

    {

    GUILayout.Box("n/a",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));

    }



    if(GUILayout.Button(tDetails.material.name,GUILayout.Width(150)))

    {

    SelectObject(tDetails.material,ctrlPressed);

    }



    string shaderLabel = tDetails.material.shader != null ? tDetails.material.shader.name : "no shader";

    GUILayout.Label (shaderLabel, GUILayout.Width(200));



    if(GUILayout.Button(tDetails.FoundInRenderers.Count+" GO",GUILayout.Width(50)))

    {

    List<Object> FoundObjects=new List<Object>();

    foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);

    SelectObjects(FoundObjects,ctrlPressed);

    }





    GUILayout.EndHorizontal();

    }

    }

    EditorGUILayout.EndScrollView();

        }



    void ListMeshes()

    {

    meshListScrollPos = EditorGUILayout.BeginScrollView(meshListScrollPos);



    foreach (MeshDetails tDetails in ActiveMeshDetails)

    {

    if (tDetails.mesh!=null)

    {

    GUILayout.BeginHorizontal ();

    /*

    if (tDetails.material.mainTexture!=null) GUILayout.Box(tDetails.material.mainTexture, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));

    else

    {

    GUILayout.Box("n/a",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));

    }

    */



    if(GUILayout.Button(tDetails.mesh.name,GUILayout.Width(150)))

    {

    SelectObject(tDetails.mesh,ctrlPressed);

    }

    string sizeLabel=""+tDetails.mesh.vertexCount+" vert";



    GUILayout.Label (sizeLabel,GUILayout.Width(100));





    if(GUILayout.Button(tDetails.FoundInMeshFilters.Count + " GO",GUILayout.Width(50)))

    {

    List<Object> FoundObjects=new List<Object>();

    foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters) FoundObjects.Add(meshFilter.gameObject);

    SelectObjects(FoundObjects,ctrlPressed);

    }



    if(GUILayout.Button(tDetails.FoundInSkinnedMeshRenderer.Count + " GO",GUILayout.Width(50)))

    {

    List<Object> FoundObjects=new List<Object>();

    foreach (SkinnedMeshRenderer skinnedMeshRenderer in tDetails.FoundInSkinnedMeshRenderer) FoundObjects.Add(skinnedMeshRenderer.gameObject);

    SelectObjects(FoundObjects,ctrlPressed);

    }





    GUILayout.EndHorizontal();

    }

    }

    EditorGUILayout.EndScrollView();

        }



    string FormatSizeString(int memSizeKB)

    {

    if (memSizeKB<1024) return ""+memSizeKB+"k";

    else

    {

    float memSizeMB=((float)memSizeKB)/1024.0f;

    return memSizeMB.ToString("0.00")+"Mb";

    }

    }





    TextureDetails FindTextureDetails(Texture tTexture)

    {

    foreach (TextureDetails tTextureDetails in ActiveTextures)

    {

    if (tTextureDetails.texture==tTexture) return tTextureDetails;

    }

    returnnull;



    }



    MaterialDetails FindMaterialDetails(Material tMaterial)

    {

    foreach (MaterialDetails tMaterialDetails in ActiveMaterials)

    {

    if (tMaterialDetails.material==tMaterial) return tMaterialDetails;

    }

    returnnull;



    }



    MeshDetails FindMeshDetails(Mesh tMesh)

    {

    foreach (MeshDetails tMeshDetails in ActiveMeshDetails)

    {

    if (tMeshDetails.mesh==tMesh) return tMeshDetails;

    }

    returnnull;



    }





    void CheckResources()

    {

    ActiveTextures.Clear();

    ActiveMaterials.Clear();

    ActiveMeshDetails.Clear();



    Renderer[] renderers = (Renderer[]) FindObjectsOfType(typeof(Renderer));

    //Debug.Log("Total renderers "+renderers.Length);

    foreach (Renderer renderer in renderers)

    {

    //Debug.Log("Renderer is "+renderer.name);

    foreach (Material material in renderer.sharedMaterials)

    {



    MaterialDetails tMaterialDetails=FindMaterialDetails(material);

    if (tMaterialDetails==null)

    {

    tMaterialDetails=new MaterialDetails();

    tMaterialDetails.material=material;

    ActiveMaterials.Add(tMaterialDetails);

    }

    tMaterialDetails.FoundInRenderers.Add(renderer);

    }

    }



    foreach (MaterialDetails tMaterialDetails in ActiveMaterials)

    {

    Material tMaterial=tMaterialDetails.material;

    foreach (Object obj in EditorUtility.CollectDependencies(new UnityEngine.Object[] {tMaterial}))

        {

    if (obj is Texture)

    {

    Texture tTexture=obj as Texture;

    TextureDetails tTextureDetails=FindTextureDetails(tTexture);

    if (tTextureDetails==null)

    {

    tTextureDetails=new TextureDetails();

    tTextureDetails.texture=tTexture;

    tTextureDetails.isCubeMap=tTexture is Cubemap;



    int memSize=CalculateTextureSizeBytes(tTexture);



    tTextureDetails.memSizeKB=memSize/1024;

    TextureFormat tFormat=TextureFormat.RGBA32;

    int tMipMapCount=1;

    if (tTexture is Texture2D)

    {

    tFormat=(tTexture as Texture2D).format;

    tMipMapCount=(tTexture as Texture2D).mipmapCount;

    }

    if (tTexture is Cubemap)

    {

    tFormat=(tTexture as Cubemap).format;

    }



    tTextureDetails.format=tFormat;

    tTextureDetails.mipMapCount=tMipMapCount;

    ActiveTextures.Add(tTextureDetails);

    }

    tTextureDetails.FoundInMaterials.Add(tMaterial);

    foreach (Renderer renderer in tMaterialDetails.FoundInRenderers)

    {

    if (!tTextureDetails.FoundInRenderers.Contains(renderer)) tTextureDetails.FoundInRenderers.Add(renderer);

    }

    }

    }

    }





    MeshFilter[] meshFilters = (MeshFilter[]) FindObjectsOfType(typeof(MeshFilter));



    foreach (MeshFilter tMeshFilter in meshFilters)

    {

    Mesh tMesh=tMeshFilter.sharedMesh;

    if (tMesh!=null)

    {

    MeshDetails tMeshDetails=FindMeshDetails(tMesh);

    if (tMeshDetails==null)

    {

    tMeshDetails=new MeshDetails();

    tMeshDetails.mesh=tMesh;

    ActiveMeshDetails.Add(tMeshDetails);

    }

    tMeshDetails.FoundInMeshFilters.Add(tMeshFilter);

    }

    }



    SkinnedMeshRenderer[] skinnedMeshRenderers = (SkinnedMeshRenderer[]) FindObjectsOfType(typeof(SkinnedMeshRenderer));



    foreach (SkinnedMeshRenderer tSkinnedMeshRenderer in skinnedMeshRenderers)

    {

    Mesh tMesh=tSkinnedMeshRenderer.sharedMesh;

    if (tMesh!=null)

    {

    MeshDetails tMeshDetails=FindMeshDetails(tMesh);

    if (tMeshDetails==null)

    {

    tMeshDetails=new MeshDetails();

    tMeshDetails.mesh=tMesh;

    ActiveMeshDetails.Add(tMeshDetails);

    }

    tMeshDetails.FoundInSkinnedMeshRenderer.Add(tSkinnedMeshRenderer);

    }

    }





    TotalTextureMemory=0;

    foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory+=tTextureDetails.memSizeKB;



    TotalMeshVertices=0;

    foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices+=tMeshDetails.mesh.vertexCount;



    // Sort by size, descending

    ActiveTextures.Sort(delegate(TextureDetails details1, TextureDetails details2) {return details2.memSizeKB-details1.memSizeKB;});

    ActiveMeshDetails.Sort(delegate(MeshDetails details1, MeshDetails details2) {return details2.mesh.vertexCount-details1.mesh.vertexCount;});



    }





    }
    展开全文
  • Tools/ResourceChecker,打开窗口即可查看 using System; using System.Linq; using UnityEngine; using UnityEngine.UI; using UnityEditor; using System.Collections.Generi...

    Tools/ResourceChecker,打开窗口即可查看

    using System;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEditor;
    using System.Collections.Generic;
    using System.Reflection;
    using Object = UnityEngine.Object;
    
    public class TextureDetails : IEquatable<TextureDetails>
    {
        public bool isCubeMap;
        public int memSizeKB;
        public Texture texture;
        public TextureFormat format;
        public int mipMapCount;
        public List<Object> FoundInMaterials = new List<Object>();
        public List<Object> FoundInRenderers = new List<Object>();
        public List<Object> FoundInAnimators = new List<Object>();
        public List<Object> FoundInScripts = new List<Object>();
        public List<Object> FoundInGraphics = new List<Object>();
        public bool isSky;
        public bool instance;
        public bool isgui;
        public TextureDetails()
        {
    
        }
    
        public bool Equals(TextureDetails other)
        {
            return texture != null && other.texture != null &&
                texture.GetNativeTexturePtr() == other.texture.GetNativeTexturePtr();
        }
    
        public override int GetHashCode()
        {
            return (int)texture.GetNativeTexturePtr();
        }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as TextureDetails);
        }
    };
    
    public class MaterialDetails
    {
    
        public Material material;
    
        public List<Renderer> FoundInRenderers = new List<Renderer>();
        public List<Graphic> FoundInGraphics = new List<Graphic>();
        public bool instance;
        public bool isgui;
        public bool isSky;
    
        public MaterialDetails()
        {
            instance = false;
            isgui = false;
            isSky = false;
        }
    };
    
    public class MeshDetails
    {
    
        public Mesh mesh;
    
        public List<MeshFilter> FoundInMeshFilters = new List<MeshFilter>();
        public List<SkinnedMeshRenderer> FoundInSkinnedMeshRenderer = new List<SkinnedMeshRenderer>();
        public bool instance;
    
        public MeshDetails()
        {
            instance = false;
        }
    };
    
    public class MissingGraphic
    {
        public Transform Object;
        public string type;
        public string name;
    }
    
    public class ResourceChecker : EditorWindow
    {
    
    
        string[] inspectToolbarStrings = { "Textures", "Materials", "Meshes" };
        string[] inspectToolbarStrings2 = { "Textures", "Materials", "Meshes", "Missing" };
    
        enum InspectType
        {
            Textures, Materials, Meshes, Missing
        };
    
        bool IncludeDisabledObjects = true;
        bool IncludeSpriteAnimations = true;
        bool IncludeScriptReferences = true;
        bool IncludeGuiElements = true;
        bool thingsMissing = false;
    
        InspectType ActiveInspectType = InspectType.Textures;
    
        float ThumbnailWidth = 40;
        float ThumbnailHeight = 40;
    
        List<TextureDetails> ActiveTextures = new List<TextureDetails>();
        List<MaterialDetails> ActiveMaterials = new List<MaterialDetails>();
        List<MeshDetails> ActiveMeshDetails = new List<MeshDetails>();
        List<MissingGraphic> MissingObjects = new List<MissingGraphic>();
    
        Vector2 textureListScrollPos = new Vector2(0, 0);
        Vector2 materialListScrollPos = new Vector2(0, 0);
        Vector2 meshListScrollPos = new Vector2(0, 0);
        Vector2 missingListScrollPos = new Vector2(0, 0);
    
        int TotalTextureMemory = 0;
        int TotalMeshVertices = 0;
    
        bool ctrlPressed = false;
    
        static int MinWidth = 475;
        Color defColor;
    
        bool collectedInPlayingMode;
    
        [MenuItem("Tools/ResourceChecker")]
        static void Init()
        {
            ResourceChecker window = (ResourceChecker)EditorWindow.GetWindow(typeof(ResourceChecker));
            window.CheckResources();
            window.minSize = new Vector2(MinWidth, 475);
        }
    
        void OnGUI()
        {
            defColor = GUI.color;
            IncludeDisabledObjects = GUILayout.Toggle(IncludeDisabledObjects, "Include disabled objects", GUILayout.Width(300));
            IncludeSpriteAnimations = GUILayout.Toggle(IncludeSpriteAnimations, "Look in sprite animations", GUILayout.Width(300));
            GUI.color = new Color(0.8f, 0.8f, 1.0f, 1.0f);
            IncludeScriptReferences = GUILayout.Toggle(IncludeScriptReferences, "Look in behavior fields", GUILayout.Width(300));
            GUI.color = new Color(1.0f, 0.95f, 0.8f, 1.0f);
            IncludeGuiElements = GUILayout.Toggle(IncludeGuiElements, "Look in GUI elements", GUILayout.Width(300));
            GUI.color = defColor;
            GUILayout.BeginArea(new Rect(position.width - 85, 5, 100, 65));
            if (GUILayout.Button("Calculate", GUILayout.Width(80), GUILayout.Height(40)))
                CheckResources();
            if (GUILayout.Button("CleanUp", GUILayout.Width(80), GUILayout.Height(20)))
                Resources.UnloadUnusedAssets();
            GUILayout.EndArea();
            RemoveDestroyedResources();
    
            GUILayout.Space(30);
            if (thingsMissing == true)
            {
                EditorGUI.HelpBox(new Rect(8, 75, 300, 25), "Some GameObjects are missing graphical elements.", MessageType.Error);
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("Textures " + ActiveTextures.Count + " - " + FormatSizeString(TotalTextureMemory));
            GUILayout.Label("Materials " + ActiveMaterials.Count);
            GUILayout.Label("Meshes " + ActiveMeshDetails.Count + " - " + TotalMeshVertices + " verts");
            GUILayout.EndHorizontal();
            if (thingsMissing == true)
            {
                ActiveInspectType = (InspectType)GUILayout.Toolbar((int)ActiveInspectType, inspectToolbarStrings2);
            }
            else
            {
                ActiveInspectType = (InspectType)GUILayout.Toolbar((int)ActiveInspectType, inspectToolbarStrings);
            }
    
            ctrlPressed = Event.current.control || Event.current.command;
    
            switch (ActiveInspectType)
            {
                case InspectType.Textures:
                    ListTextures();
                    break;
                case InspectType.Materials:
                    ListMaterials();
                    break;
                case InspectType.Meshes:
                    ListMeshes();
                    break;
                case InspectType.Missing:
                    ListMissing();
                    break;
            }
        }
    
        private void RemoveDestroyedResources()
        {
            if (collectedInPlayingMode != Application.isPlaying)
            {
                ActiveTextures.Clear();
                ActiveMaterials.Clear();
                ActiveMeshDetails.Clear();
                MissingObjects.Clear();
                thingsMissing = false;
                collectedInPlayingMode = Application.isPlaying;
            }
    
            ActiveTextures.RemoveAll(x => !x.texture);
            ActiveTextures.ForEach(delegate (TextureDetails obj)
            {
                obj.FoundInAnimators.RemoveAll(x => !x);
                obj.FoundInMaterials.RemoveAll(x => !x);
                obj.FoundInRenderers.RemoveAll(x => !x);
                obj.FoundInScripts.RemoveAll(x => !x);
                obj.FoundInGraphics.RemoveAll(x => !x);
            });
    
            ActiveMaterials.RemoveAll(x => !x.material);
            ActiveMaterials.ForEach(delegate (MaterialDetails obj)
            {
                obj.FoundInRenderers.RemoveAll(x => !x);
                obj.FoundInGraphics.RemoveAll(x => !x);
            });
    
            ActiveMeshDetails.RemoveAll(x => !x.mesh);
            ActiveMeshDetails.ForEach(delegate (MeshDetails obj)
            {
                obj.FoundInMeshFilters.RemoveAll(x => !x);
                obj.FoundInSkinnedMeshRenderer.RemoveAll(x => !x);
            });
    
            TotalTextureMemory = 0;
            foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB;
    
            TotalMeshVertices = 0;
            foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount;
        }
    
        int GetBitsPerPixel(TextureFormat format)
        {
            switch (format)
            {
                case TextureFormat.Alpha8: //    Alpha-only texture format.
                    return 8;
                case TextureFormat.ARGB4444: //  A 16 bits/pixel texture format. Texture stores color with an alpha channel.
                    return 16;
                case TextureFormat.RGBA4444: //  A 16 bits/pixel texture format.
                    return 16;
                case TextureFormat.RGB24:   // A color texture format.
                    return 24;
                case TextureFormat.RGBA32:  //Color with an alpha channel texture format.
                    return 32;
                case TextureFormat.ARGB32:  //Color with an alpha channel texture format.
                    return 32;
                case TextureFormat.RGB565:  //   A 16 bit color texture format.
                    return 16;
                case TextureFormat.DXT1:    // Compressed color texture format.
                    return 4;
                case TextureFormat.DXT5:    // Compressed color with alpha channel texture format.
                    return 8;
                /*
                case TextureFormat.WiiI4:   // Wii texture format.
                case TextureFormat.WiiI8:   // Wii texture format. Intensity 8 bit.
                case TextureFormat.WiiIA4:  // Wii texture format. Intensity + Alpha 8 bit (4 + 4).
                case TextureFormat.WiiIA8:  // Wii texture format. Intensity + Alpha 16 bit (8 + 8).
                case TextureFormat.WiiRGB565:   // Wii texture format. RGB 16 bit (565).
                case TextureFormat.WiiRGB5A3:   // Wii texture format. RGBA 16 bit (4443).
                case TextureFormat.WiiRGBA8:    // Wii texture format. RGBA 32 bit (8888).
                case TextureFormat.WiiCMPR: //   Compressed Wii texture format. 4 bits/texel, ~RGB8A1 (Outline alpha is not currently supported).
                    return 0;  //Not supported yet
                */
                case TextureFormat.PVRTC_RGB2://     PowerVR (iOS) 2 bits/pixel compressed color texture format.
                    return 2;
                case TextureFormat.PVRTC_RGBA2://    PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format
                    return 2;
                case TextureFormat.PVRTC_RGB4://     PowerVR (iOS) 4 bits/pixel compressed color texture format.
                    return 4;
                case TextureFormat.PVRTC_RGBA4://    PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format
                    return 4;
                case TextureFormat.ETC_RGB4://   ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.
                    return 4;
                case TextureFormat.ATC_RGB4://   ATC (ATITC) 4 bits/pixel compressed RGB texture format.
                    return 4;
                case TextureFormat.ATC_RGBA8://  ATC (ATITC) 8 bits/pixel compressed RGB texture format.
                    return 8;
                case TextureFormat.BGRA32://     Format returned by iPhone camera
                    return 32;
    #if !UNITY_5
                case TextureFormat.ATF_RGB_DXT1://   Flash-specific RGB DXT1 compressed color texture format.
                case TextureFormat.ATF_RGBA_JPG://   Flash-specific RGBA JPG-compressed color texture format.
                case TextureFormat.ATF_RGB_JPG://    Flash-specific RGB JPG-compressed color texture format.
                return 0; //Not supported yet  
    #endif
            }
            return 0;
        }
    
        int CalculateTextureSizeBytes(Texture tTexture)
        {
    
            int tWidth = tTexture.width;
            int tHeight = tTexture.height;
            if (tTexture is Texture2D)
            {
                Texture2D tTex2D = tTexture as Texture2D;
                int bitsPerPixel = GetBitsPerPixel(tTex2D.format);
                int mipMapCount = tTex2D.mipmapCount;
                int mipLevel = 1;
                int tSize = 0;
                while (mipLevel <= mipMapCount)
                {
                    tSize += tWidth * tHeight * bitsPerPixel / 8;
                    tWidth = tWidth / 2;
                    tHeight = tHeight / 2;
                    mipLevel++;
                }
                return tSize;
            }
            if (tTexture is Texture2DArray)
            {
                Texture2DArray tTex2D = tTexture as Texture2DArray;
                int bitsPerPixel = GetBitsPerPixel(tTex2D.format);
                int mipMapCount = 10;
                int mipLevel = 1;
                int tSize = 0;
                while (mipLevel <= mipMapCount)
                {
                    tSize += tWidth * tHeight * bitsPerPixel / 8;
                    tWidth = tWidth / 2;
                    tHeight = tHeight / 2;
                    mipLevel++;
                }
                return tSize * ((Texture2DArray)tTex2D).depth;
            }
            if (tTexture is Cubemap)
            {
                Cubemap tCubemap = tTexture as Cubemap;
                int bitsPerPixel = GetBitsPerPixel(tCubemap.format);
                return tWidth * tHeight * 6 * bitsPerPixel / 8;
            }
            return 0;
        }
    
    
        void SelectObject(Object selectedObject, bool append)
        {
            if (append)
            {
                List<Object> currentSelection = new List<Object>(Selection.objects);
                // Allow toggle selection
                if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject);
                else currentSelection.Add(selectedObject);
    
                Selection.objects = currentSelection.ToArray();
            }
            else Selection.activeObject = selectedObject;
        }
    
        void SelectObjects(List<Object> selectedObjects, bool append)
        {
            if (append)
            {
                List<Object> currentSelection = new List<Object>(Selection.objects);
                currentSelection.AddRange(selectedObjects);
                Selection.objects = currentSelection.ToArray();
            }
            else Selection.objects = selectedObjects.ToArray();
        }
    
        void ListTextures()
        {
            textureListScrollPos = EditorGUILayout.BeginScrollView(textureListScrollPos);
    
            foreach (TextureDetails tDetails in ActiveTextures)
            {
    
                GUILayout.BeginHorizontal();
                Texture tex = new Texture();
                tex = tDetails.texture;
                if (tDetails.texture.GetType() == typeof(Texture2DArray) || tDetails.texture.GetType() == typeof(Cubemap))
                {
                    tex = AssetPreview.GetMiniThumbnail(tDetails.texture);
                }
                GUILayout.Box(tex, GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
    
                if (tDetails.instance == true)
                    GUI.color = new Color(0.8f, 0.8f, defColor.b, 1.0f);
                if (tDetails.isgui == true)
                    GUI.color = new Color(defColor.r, 0.95f, 0.8f, 1.0f);
                if (tDetails.isSky)
                    GUI.color = new Color(0.9f, defColor.g, defColor.b, 1.0f);
                if (GUILayout.Button(tDetails.texture.name, GUILayout.Width(150)))
                {
                    SelectObject(tDetails.texture, ctrlPressed);
                }
                GUI.color = defColor;
    
                string sizeLabel = "" + tDetails.texture.width + "x" + tDetails.texture.height;
                if (tDetails.isCubeMap) sizeLabel += "x6";
                if (tDetails.texture.GetType() == typeof(Texture2DArray))
                    sizeLabel += "[]\n" + ((Texture2DArray)tDetails.texture).depth + "depths";
                sizeLabel += " - " + tDetails.mipMapCount + "mip\n" + FormatSizeString(tDetails.memSizeKB) + " - " + tDetails.format;
    
                GUILayout.Label(sizeLabel, GUILayout.Width(120));
    
                if (GUILayout.Button(tDetails.FoundInMaterials.Count + " Mat", GUILayout.Width(50)))
                {
                    SelectObjects(tDetails.FoundInMaterials, ctrlPressed);
                }
    
                HashSet<Object> FoundObjects = new HashSet<Object>();
                foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
                foreach (Animator animator in tDetails.FoundInAnimators) FoundObjects.Add(animator.gameObject);
                foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject);
                foreach (MonoBehaviour script in tDetails.FoundInScripts) FoundObjects.Add(script.gameObject);
                if (GUILayout.Button(FoundObjects.Count + " GO", GUILayout.Width(50)))
                {
                    SelectObjects(new List<Object>(FoundObjects), ctrlPressed);
                }
    
                GUILayout.EndHorizontal();
            }
            if (ActiveTextures.Count > 0)
            {
                EditorGUILayout.Space();
                GUILayout.BeginHorizontal();
                //GUILayout.Box(" ",GUILayout.Width(ThumbnailWidth),GUILayout.Height(ThumbnailHeight));
                if (GUILayout.Button("Select \n All", GUILayout.Width(ThumbnailWidth * 2)))
                {
                    List<Object> AllTextures = new List<Object>();
                    foreach (TextureDetails tDetails in ActiveTextures) AllTextures.Add(tDetails.texture);
                    SelectObjects(AllTextures, ctrlPressed);
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndScrollView();
        }
    
        void ListMaterials()
        {
            materialListScrollPos = EditorGUILayout.BeginScrollView(materialListScrollPos);
    
            foreach (MaterialDetails tDetails in ActiveMaterials)
            {
                if (tDetails.material != null)
                {
                    GUILayout.BeginHorizontal();
    
                    GUILayout.Box(AssetPreview.GetAssetPreview(tDetails.material), GUILayout.Width(ThumbnailWidth), GUILayout.Height(ThumbnailHeight));
    
                    if (tDetails.instance == true)
                        GUI.color = new Color(0.8f, 0.8f, defColor.b, 1.0f);
                    if (tDetails.isgui == true)
                        GUI.color = new Color(defColor.r, 0.95f, 0.8f, 1.0f);
                    if (tDetails.isSky)
                        GUI.color = new Color(0.9f, defColor.g, defColor.b, 1.0f);
                    if (GUILayout.Button(tDetails.material.name, GUILayout.Width(150)))
                    {
                        SelectObject(tDetails.material, ctrlPressed);
                    }
                    GUI.color = defColor;
    
                    string shaderLabel = tDetails.material.shader != null ? tDetails.material.shader.name : "no shader";
                    GUILayout.Label(shaderLabel, GUILayout.Width(200));
    
                    if (GUILayout.Button((tDetails.FoundInRenderers.Count + tDetails.FoundInGraphics.Count) + " GO", GUILayout.Width(50)))
                    {
                        List<Object> FoundObjects = new List<Object>();
                        foreach (Renderer renderer in tDetails.FoundInRenderers) FoundObjects.Add(renderer.gameObject);
                        foreach (Graphic graphic in tDetails.FoundInGraphics) FoundObjects.Add(graphic.gameObject);
                        SelectObjects(FoundObjects, ctrlPressed);
                    }
    
    
                    GUILayout.EndHorizontal();
                }
            }
            EditorGUILayout.EndScrollView();
        }
    
        void ListMeshes()
        {
            meshListScrollPos = EditorGUILayout.BeginScrollView(meshListScrollPos);
    
            foreach (MeshDetails tDetails in ActiveMeshDetails)
            {
                if (tDetails.mesh != null)
                {
                    GUILayout.BeginHorizontal();
                    string name = tDetails.mesh.name;
                    if (name == null || name.Count() < 1)
                        name = tDetails.FoundInMeshFilters[0].gameObject.name;
                    if (tDetails.instance == true)
                        GUI.color = new Color(0.8f, 0.8f, defColor.b, 1.0f);
                    if (GUILayout.Button(name, GUILayout.Width(150)))
                    {
                        SelectObject(tDetails.mesh, ctrlPressed);
                    }
                    GUI.color = defColor;
                    string sizeLabel = "" + tDetails.mesh.vertexCount + " vert";
    
                    GUILayout.Label(sizeLabel, GUILayout.Width(100));
    
    
                    if (GUILayout.Button(tDetails.FoundInMeshFilters.Count + " GO", GUILayout.Width(50)))
                    {
                        List<Object> FoundObjects = new List<Object>();
                        foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters) FoundObjects.Add(meshFilter.gameObject);
                        SelectObjects(FoundObjects, ctrlPressed);
                    }
                    if (tDetails.FoundInSkinnedMeshRenderer.Count > 0)
                    {
                        if (GUILayout.Button(tDetails.FoundInSkinnedMeshRenderer.Count + " skinned mesh GO", GUILayout.Width(140)))
                        {
                            List<Object> FoundObjects = new List<Object>();
                            foreach (SkinnedMeshRenderer skinnedMeshRenderer in tDetails.FoundInSkinnedMeshRenderer)
                                FoundObjects.Add(skinnedMeshRenderer.gameObject);
                            SelectObjects(FoundObjects, ctrlPressed);
                        }
                    }
                    else
                    {
                        GUI.color = new Color(defColor.r, defColor.g, defColor.b, 0.5f);
                        GUILayout.Label("   0 skinned mesh");
                        GUI.color = defColor;
                    }
    
    
                    GUILayout.EndHorizontal();
                }
            }
            EditorGUILayout.EndScrollView();
        }
    
        void ListMissing()
        {
            missingListScrollPos = EditorGUILayout.BeginScrollView(missingListScrollPos);
            foreach (MissingGraphic dMissing in MissingObjects)
            {
                GUILayout.BeginHorizontal();
                if (GUILayout.Button(dMissing.name, GUILayout.Width(150)))
                    SelectObject(dMissing.Object, ctrlPressed);
                GUILayout.Label("missing ", GUILayout.Width(48));
                switch (dMissing.type)
                {
                    case "mesh":
                        GUI.color = new Color(0.8f, 0.8f, defColor.b, 1.0f);
                        break;
                    case "sprite":
                        GUI.color = new Color(defColor.r, 0.8f, 0.8f, 1.0f);
                        break;
                    case "material":
                        GUI.color = new Color(0.8f, defColor.g, 0.8f, 1.0f);
                        break;
                }
                GUILayout.Label(dMissing.type);
                GUI.color = defColor;
                GUILayout.EndHorizontal();
            }
            EditorGUILayout.EndScrollView();
        }
    
        string FormatSizeString(int memSizeKB)
        {
            if (memSizeKB < 1024) return "" + memSizeKB + "k";
            else
            {
                float memSizeMB = ((float)memSizeKB) / 1024.0f;
                return memSizeMB.ToString("0.00") + "Mb";
            }
        }
    
    
        TextureDetails FindTextureDetails(Texture tTexture)
        {
            foreach (TextureDetails tTextureDetails in ActiveTextures)
            {
                if (tTextureDetails.texture == tTexture) return tTextureDetails;
            }
            return null;
    
        }
    
        MaterialDetails FindMaterialDetails(Material tMaterial)
        {
            foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
            {
                if (tMaterialDetails.material == tMaterial) return tMaterialDetails;
            }
            return null;
    
        }
    
        MeshDetails FindMeshDetails(Mesh tMesh)
        {
            foreach (MeshDetails tMeshDetails in ActiveMeshDetails)
            {
                if (tMeshDetails.mesh == tMesh) return tMeshDetails;
            }
            return null;
    
        }
    
    
        void CheckResources()
        {
            ActiveTextures.Clear();
            ActiveMaterials.Clear();
            ActiveMeshDetails.Clear();
            MissingObjects.Clear();
            thingsMissing = false;
    
            Renderer[] renderers = FindObjects<Renderer>();
    
            MaterialDetails skyMat = new MaterialDetails();
            skyMat.material = RenderSettings.skybox;
            skyMat.isSky = true;
            ActiveMaterials.Add(skyMat);
    
            //Debug.Log("Total renderers "+renderers.Length);
            foreach (Renderer renderer in renderers)
            {
                //Debug.Log("Renderer is "+renderer.name);
                foreach (Material material in renderer.sharedMaterials)
                {
    
                    MaterialDetails tMaterialDetails = FindMaterialDetails(material);
                    if (tMaterialDetails == null)
                    {
                        tMaterialDetails = new MaterialDetails();
                        tMaterialDetails.material = material;
                        ActiveMaterials.Add(tMaterialDetails);
                    }
                    tMaterialDetails.FoundInRenderers.Add(renderer);
                }
    
                if (renderer is SpriteRenderer)
                {
                    SpriteRenderer tSpriteRenderer = (SpriteRenderer)renderer;
    
                    if (tSpriteRenderer.sprite != null)
                    {
                        var tSpriteTextureDetail = GetTextureDetail(tSpriteRenderer.sprite.texture, renderer);
                        if (!ActiveTextures.Contains(tSpriteTextureDetail))
                        {
                            ActiveTextures.Add(tSpriteTextureDetail);
                        }
                    }
                    else if (tSpriteRenderer.sprite == null)
                    {
                        MissingGraphic tMissing = new MissingGraphic();
                        tMissing.Object = tSpriteRenderer.transform;
                        tMissing.type = "sprite";
                        tMissing.name = tSpriteRenderer.transform.name;
                        MissingObjects.Add(tMissing);
                        thingsMissing = true;
                    }
                }
            }
    
            if (IncludeGuiElements)
            {
                Graphic[] graphics = FindObjects<Graphic>();
    
                foreach (Graphic graphic in graphics)
                {
                    if (graphic.mainTexture)
                    {
                        var tSpriteTextureDetail = GetTextureDetail(graphic.mainTexture, graphic);
                        if (!ActiveTextures.Contains(tSpriteTextureDetail))
                        {
                            ActiveTextures.Add(tSpriteTextureDetail);
                        }
                    }
    
                    if (graphic.materialForRendering)
                    {
                        MaterialDetails tMaterialDetails = FindMaterialDetails(graphic.materialForRendering);
                        if (tMaterialDetails == null)
                        {
                            tMaterialDetails = new MaterialDetails();
                            tMaterialDetails.material = graphic.materialForRendering;
                            tMaterialDetails.isgui = true;
                            ActiveMaterials.Add(tMaterialDetails);
                        }
                        tMaterialDetails.FoundInGraphics.Add(graphic);
                    }
                }
            }
    
            foreach (MaterialDetails tMaterialDetails in ActiveMaterials)
            {
                Material tMaterial = tMaterialDetails.material;
                if (tMaterial != null)
                {
                    var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
                    foreach (Object obj in dependencies)
                    {
                        if (obj is Texture)
                        {
                            Texture tTexture = obj as Texture;
                            var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMaterialDetails);
                            tTextureDetail.isSky = tMaterialDetails.isSky;
                            tTextureDetail.instance = tMaterialDetails.instance;
                            tTextureDetail.isgui = tMaterialDetails.isgui;
                            ActiveTextures.Add(tTextureDetail);
                        }
                    }
    
                    //if the texture was downloaded, it won't be included in the editor dependencies
                    if (tMaterial.HasProperty("_MainTex"))
                    {
                        if (tMaterial.mainTexture != null && !dependencies.Contains(tMaterial.mainTexture))
                        {
                            var tTextureDetail = GetTextureDetail(tMaterial.mainTexture, tMaterial, tMaterialDetails);
                            ActiveTextures.Add(tTextureDetail);
                        }
                    }
                }
            }
    
    
            MeshFilter[] meshFilters = FindObjects<MeshFilter>();
    
            foreach (MeshFilter tMeshFilter in meshFilters)
            {
                Mesh tMesh = tMeshFilter.sharedMesh;
                if (tMesh != null)
                {
                    MeshDetails tMeshDetails = FindMeshDetails(tMesh);
                    if (tMeshDetails == null)
                    {
                        tMeshDetails = new MeshDetails();
                        tMeshDetails.mesh = tMesh;
                        ActiveMeshDetails.Add(tMeshDetails);
                    }
                    tMeshDetails.FoundInMeshFilters.Add(tMeshFilter);
                }
                else if (tMesh == null && tMeshFilter.transform.GetComponent("TextContainer") == null)
                {
                    MissingGraphic tMissing = new MissingGraphic();
                    tMissing.Object = tMeshFilter.transform;
                    tMissing.type = "mesh";
                    tMissing.name = tMeshFilter.transform.name;
                    MissingObjects.Add(tMissing);
                    thingsMissing = true;
                }
                if (tMeshFilter.transform.GetComponent<MeshRenderer>().sharedMaterial == null)
                {
                    MissingGraphic tMissing = new MissingGraphic();
                    tMissing.Object = tMeshFilter.transform;
                    tMissing.type = "material";
                    tMissing.name = tMeshFilter.transform.name;
                    MissingObjects.Add(tMissing);
                    thingsMissing = true;
                }
            }
    
            SkinnedMeshRenderer[] skinnedMeshRenderers = FindObjects<SkinnedMeshRenderer>();
    
            foreach (SkinnedMeshRenderer tSkinnedMeshRenderer in skinnedMeshRenderers)
            {
                Mesh tMesh = tSkinnedMeshRenderer.sharedMesh;
                if (tMesh != null)
                {
                    MeshDetails tMeshDetails = FindMeshDetails(tMesh);
                    if (tMeshDetails == null)
                    {
                        tMeshDetails = new MeshDetails();
                        tMeshDetails.mesh = tMesh;
                        ActiveMeshDetails.Add(tMeshDetails);
                    }
                    tMeshDetails.FoundInSkinnedMeshRenderer.Add(tSkinnedMeshRenderer);
                }
                else if (tMesh == null)
                {
                    MissingGraphic tMissing = new MissingGraphic();
                    tMissing.Object = tSkinnedMeshRenderer.transform;
                    tMissing.type = "mesh";
                    tMissing.name = tSkinnedMeshRenderer.transform.name;
                    MissingObjects.Add(tMissing);
                    thingsMissing = true;
                }
                if (tSkinnedMeshRenderer.sharedMaterial == null)
                {
                    MissingGraphic tMissing = new MissingGraphic();
                    tMissing.Object = tSkinnedMeshRenderer.transform;
                    tMissing.type = "material";
                    tMissing.name = tSkinnedMeshRenderer.transform.name;
                    MissingObjects.Add(tMissing);
                    thingsMissing = true;
                }
            }
    
            if (IncludeSpriteAnimations)
            {
                Animator[] animators = FindObjects<Animator>();
                foreach (Animator anim in animators)
                {
    #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
                    UnityEditorInternal.AnimatorController ac = anim.runtimeAnimatorController as UnityEditorInternal.AnimatorController;
    #elif UNITY_5
                    UnityEditor.Animations.AnimatorController ac = anim.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
    #endif
    
                    //Skip animators without layers, this can happen if they don't have an animator controller.
                    if (!ac || ac.layers == null || ac.layers.Length == 0)
                        continue;
    
                    for (int x = 0; x < anim.layerCount; x++)
                    {
    #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
                        UnityEditorInternal.StateMachine sm = ac.GetLayer(x).stateMachine;
                        int cnt = sm.stateCount;
    #elif UNITY_5
                        UnityEditor.Animations.AnimatorStateMachine sm = ac.layers[x].stateMachine;
                        int cnt = sm.states.Length;
    #endif
    
                        for (int i = 0; i < cnt; i++)
                        {
    #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3
                            UnityEditorInternal.State state = sm.GetState(i);
                            Motion m = state.GetMotion();
    #elif UNITY_5
                            UnityEditor.Animations.AnimatorState state = sm.states[i].state;
                            Motion m = state.motion;
    #endif
                            if (m != null)
                            {
                                AnimationClip clip = m as AnimationClip;
    
                                if (clip != null)
                                {
                                    EditorCurveBinding[] ecbs = AnimationUtility.GetObjectReferenceCurveBindings(clip);
    
                                    foreach (EditorCurveBinding ecb in ecbs)
                                    {
                                        if (ecb.propertyName == "m_Sprite")
                                        {
                                            foreach (ObjectReferenceKeyframe keyframe in AnimationUtility.GetObjectReferenceCurve(clip, ecb))
                                            {
                                                Sprite tSprite = keyframe.value as Sprite;
    
                                                if (tSprite != null)
                                                {
                                                    var tTextureDetail = GetTextureDetail(tSprite.texture, anim);
                                                    if (!ActiveTextures.Contains(tTextureDetail))
                                                    {
                                                        ActiveTextures.Add(tTextureDetail);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
    
                }
            }
    
            if (IncludeScriptReferences)
            {
                MonoBehaviour[] scripts = FindObjects<MonoBehaviour>();
                foreach (MonoBehaviour script in scripts)
                {
                    BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; // only public non-static fields are bound to by Unity.
                    FieldInfo[] fields = script.GetType().GetFields(flags);
    
                    foreach (FieldInfo field in fields)
                    {
                        System.Type fieldType = field.FieldType;
                        if (fieldType == typeof(Sprite))
                        {
                            Sprite tSprite = field.GetValue(script) as Sprite;
                            if (tSprite != null)
                            {
                                var tSpriteTextureDetail = GetTextureDetail(tSprite.texture, script);
                                if (!ActiveTextures.Contains(tSpriteTextureDetail))
                                {
                                    ActiveTextures.Add(tSpriteTextureDetail);
                                }
                            }
                        }
                        if (fieldType == typeof(Mesh))
                        {
                            Mesh tMesh = field.GetValue(script) as Mesh;
                            if (tMesh != null)
                            {
                                MeshDetails tMeshDetails = FindMeshDetails(tMesh);
                                if (tMeshDetails == null)
                                {
                                    tMeshDetails = new MeshDetails();
                                    tMeshDetails.mesh = tMesh;
                                    tMeshDetails.instance = true;
                                    ActiveMeshDetails.Add(tMeshDetails);
                                }
                            }
                        }
                        if (fieldType == typeof(Material))
                        {
                            Material tMaterial = field.GetValue(script) as Material;
                            if (tMaterial != null)
                            {
                                MaterialDetails tMatDetails = FindMaterialDetails(tMaterial);
                                if (tMatDetails == null)
                                {
                                    tMatDetails = new MaterialDetails();
                                    tMatDetails.instance = true;
                                    tMatDetails.material = tMaterial;
                                    if (!ActiveMaterials.Contains(tMatDetails))
                                        ActiveMaterials.Add(tMatDetails);
                                }
                                if (tMaterial.mainTexture)
                                {
                                    var tSpriteTextureDetail = GetTextureDetail(tMaterial.mainTexture);
                                    if (!ActiveTextures.Contains(tSpriteTextureDetail))
                                    {
                                        ActiveTextures.Add(tSpriteTextureDetail);
                                    }
                                }
                                var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
                                foreach (Object obj in dependencies)
                                {
                                    if (obj is Texture)
                                    {
                                        Texture tTexture = obj as Texture;
                                        var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMatDetails);
                                        if (!ActiveTextures.Contains(tTextureDetail))
                                            ActiveTextures.Add(tTextureDetail);
                                    }
                                }
                            }
                        }
                    }
                }
            }
    
            TotalTextureMemory = 0;
            foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB;
    
            TotalMeshVertices = 0;
            foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount;
    
            // Sort by size, descending
            ActiveTextures.Sort(delegate (TextureDetails details1, TextureDetails details2) { return details2.memSizeKB - details1.memSizeKB; });
            ActiveTextures = ActiveTextures.Distinct().ToList();
            ActiveMeshDetails.Sort(delegate (MeshDetails details1, MeshDetails details2) { return details2.mesh.vertexCount - details1.mesh.vertexCount; });
    
            collectedInPlayingMode = Application.isPlaying;
        }
    
        private static GameObject[] GetAllRootGameObjects()
        {
    #if !UNITY_5_3_OR_NEWER
            return UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects().ToArray();
    #else
            List<GameObject> allGo = new List<GameObject>();
            for (int sceneIdx = 0; sceneIdx < UnityEngine.SceneManagement.SceneManager.sceneCount; ++sceneIdx)
            {
                allGo.AddRange(UnityEngine.SceneManagement.SceneManager.GetSceneAt(sceneIdx).GetRootGameObjects().ToArray());
            }
            return allGo.ToArray();
    #endif
        }
    
        private T[] FindObjects<T>() where T : Object
        {
            if (IncludeDisabledObjects)
            {
                List<T> meshfilters = new List<T>();
                GameObject[] allGo = GetAllRootGameObjects();
                foreach (GameObject go in allGo)
                {
                    Transform[] tgo = go.GetComponentsInChildren<Transform>(true).ToArray();
                    foreach (Transform tr in tgo)
                    {
                        if (tr.GetComponent<T>())
                            meshfilters.Add(tr.GetComponent<T>());
                    }
                }
                return (T[])meshfilters.ToArray();
            }
            else
                return (T[])FindObjectsOfType(typeof(T));
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture, Material tMaterial, MaterialDetails tMaterialDetails)
        {
            TextureDetails tTextureDetails = GetTextureDetail(tTexture);
    
            tTextureDetails.FoundInMaterials.Add(tMaterial);
            foreach (Renderer renderer in tMaterialDetails.FoundInRenderers)
            {
                if (!tTextureDetails.FoundInRenderers.Contains(renderer)) tTextureDetails.FoundInRenderers.Add(renderer);
            }
            return tTextureDetails;
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture, Renderer renderer)
        {
            TextureDetails tTextureDetails = GetTextureDetail(tTexture);
    
            tTextureDetails.FoundInRenderers.Add(renderer);
            return tTextureDetails;
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture, Animator animator)
        {
            TextureDetails tTextureDetails = GetTextureDetail(tTexture);
    
            tTextureDetails.FoundInAnimators.Add(animator);
            return tTextureDetails;
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture, Graphic graphic)
        {
            TextureDetails tTextureDetails = GetTextureDetail(tTexture);
    
            tTextureDetails.FoundInGraphics.Add(graphic);
            return tTextureDetails;
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture, MonoBehaviour script)
        {
            TextureDetails tTextureDetails = GetTextureDetail(tTexture);
    
            tTextureDetails.FoundInScripts.Add(script);
            return tTextureDetails;
        }
    
        private TextureDetails GetTextureDetail(Texture tTexture)
        {
            TextureDetails tTextureDetails = FindTextureDetails(tTexture);
            if (tTextureDetails == null)
            {
                tTextureDetails = new TextureDetails();
                tTextureDetails.texture = tTexture;
                tTextureDetails.isCubeMap = tTexture is Cubemap;
    
                int memSize = CalculateTextureSizeBytes(tTexture);
    
                TextureFormat tFormat = TextureFormat.RGBA32;
                int tMipMapCount = 1;
                if (tTexture is Texture2D)
                {
                    tFormat = (tTexture as Texture2D).format;
                    tMipMapCount = (tTexture as Texture2D).mipmapCount;
                }
                if (tTexture is Cubemap)
                {
                    tFormat = (tTexture as Cubemap).format;
                    memSize = 8 * tTexture.height * tTexture.width;
                }
                if (tTexture is Texture2DArray)
                {
                    tFormat = (tTexture as Texture2DArray).format;
                    tMipMapCount = 10;
                }
    
                tTextureDetails.memSizeKB = memSize / 1024;
                tTextureDetails.format = tFormat;
                tTextureDetails.mipMapCount = tMipMapCount;
    
            }
    
            return tTextureDetails;
        }
    
    }
    
    
    
    展开全文
  • 通常在变换场景后,上个场景中除了使用 DontDestroyOnLoad() 保留的物件,将会被释放掉,但如果在没有变换场景的情形下,想把未使用的资源卸载掉,该如何做呢? 一般情况下,我们会利用 Unity 的编辑器来部属每个...

    通常在变换场景后,上个场景中除了使用 DontDestroyOnLoad() 保留的物件,将会被释放掉,但如果在没有变换场景的情形下,想把未使用的资源卸载掉,该如何做呢?

    一般情况下,我们会利用 Unity 的编辑器来部属每个关卡或场景中的物件,这些物件在载入场景后都是必要的,也不太会持续增加物件数,在关卡结束后即转换到下个场景,所以原本场景中的物件 将不再需要,所以 Unity 将会自动将前一场景的物件都销毁掉,所以我们通常不太需要去管理记忆体的使用或是否释放,但如果你的游戏全部是在单一个场景中运行的,那麼物件的產生、销 毁、释放资源等等的动作就变得格外重要。

    我做了一个宝石类型的游戏,画面上除了 GUI 及背景外就只有宝石,所以我事先将宝石做成 Prefabs ,在需要时利用 Instantiate() 產生,我在不同的关卡利用 renderer.material.mainTexture 变更背景图,利用 GetComponent(MeshFilter).sharedMesh 变更宝石的形状以及利用 renderer.material.color 变更宝石顏色,如此一个Prefabs 可以重复无限使用,所以在游戏场景中只设置了简单几个场景物件,在这种场景不需要变化太多的情况下,每个关卡都换场景重新配置一样的物件似乎有点多餘,所 以这个游戏便只有一个场景,在需要时產生宝石,然后再视情况使用 Destroy() 销毁掉,这样看起来只要在產生宝石时控制画面上的物件数量,那麼也就不用担心记忆体使用过量或没释放掉的问题。

    但是,这个游戏在连续玩好几个关卡后,也就是连续玩一段时间后,会发生停顿或画面变慢的问题,游戏刚开始玩时是相当顺畅的,但长时间执行将使效能降低,直 觉上的判断应该是记忆体累积到一定程度造成的,每个物件在不使用时都使用 Destroy() 销毁掉,那麼,堆积的记忆体是从哪裡来的呢?
    打开 Profiler 视窗看看,会发现其中的 Memory 的 Total Object Count 数值,不断的增减变化,但随着时间的增加会慢慢的往上累积,查看官网 (http://unity3d.com/support/documentation/Manual/Profiler.html) 是这样说的 “If this number rises over time then it means your game is creating some objects that are never destroyed.”,有些物件未销燬,很奇怪吧!都有使用 Destroy(),那為何还有未销毁的物件?其实,主要是因為我这裡有对 renderer.material 设置改变其内容,在这个执行时期并不会真的去改变 Project 中的 material,而是產生这个物件实例(instance) 的材质实例以供该物件使用,所以如果只是 Destroy(gameObject) 的话,将会残留部份物件数,每个產生的物件都残留一点点的话,慢慢的长时间下来将会累积相当多,记忆体将会不敷使用,所以在 Destroy(gameObject) 的同时,应该也要 Destroy(renderer.material) 才行。

    如果程式结构简单,给物件使用的 Script 档案也不多的话,也许多加一句并不困难,但我们有时候无法确定是否有在适当时机為每个物件做到完整的销毁,也许还有残留别的东西也会有这种情形持续累积记 忆体,这时又该寻找更简单统一的方法了,於是我们可以在每个关卡开始前或结束时执行一句 Resources.UnloadUnusedAssets() ,让 Unity 自行去卸载掉不使用的资源,如此在平时物件销毁时,我们已经先行释放掉大部份不使用的资源,然后再由 Resources.UnloadUnusedAssets() 卸载我们未清理掉的部份,如此的话查看 Profiler 视窗的 Memory 的 Total Object Count 数值就可以维持在一定范围内起伏,而不再随着时间增加,当然我们在关卡设置上都会有难度上的差异,在某些关卡裡,玩家可能必须花较多时间才能完成关卡,所 以如果我们只在关卡开始或结束时使用 Resources.UnloadUnusedAssets() 也许会不够,此时也可另外定义每过一段时间就执行 Resources.UnloadUnusedAssets() ,如此将可避免掉系统资源不足的问题。



    来处:http://www.comedreams.com/index.php/archives/41105

    展开全文
  • unity3d打包的所有文件是会被记录而且被排序的。所以这大大方便了我们分析为何打包文件如此之大,以及怎么减少打包文件。  日志目录一般在:C:\Users\Administrator\AppData\Local\Unity\Editor  打开log文件,...
  • 运行模式和编辑模式是完全不同的,编辑模式下可以放很多很多资源,这些资源并不是全部打包到发布的游戏包中的。 打包时,Unity会自动过滤掉没有引用的资源,注意:Resources目录和StreamingAssets目录下的会都打包...
  • 随着项目的研发进度,Asset数量也会爆发式地增长,资源管理面临很大...本文介绍的这个工具可以自动分析查找项目中未使用到的资源,在选择删除的时候还可以将这些文件打包备份,确保资源的安全性、提高项目管理的效率。
  • 至于我在看的实战核心技术的第十章MVC设计框架,提供了一堆无用的代码,然后让你去看他的课程,我就自己研究一下如何从Asset中加载到场景中,又如何在场景中释放资源。   总结一下网上一共有三种方法(这次最终...
  • 很多刚刚接触Unity3d的童鞋花了大量的时间自学,可总是把握不好Unity3d的烘焙,刚从一个坑里爬出来,又陷入另一个新的坑,每次烘焙一个场景少则几个小时,多则几十个小时,机器总是处于假死机状态,半天看不到结果,...
  • 摘要unity3d中的material再更换数次shader后,property的信息会残留,这会导致material select depedency的时候,发现其引用了根本没用到的texture(原因是曾经用过的shader中的property没有被去掉),这里提供了一...
  • 当我们在unity中使用材质的时候,我们会发现,当这个材质切换到上一个...但是如果它依赖了其他的资源,那么就可能造成不必要的资源冗余等问题,简单来说就是寻找一种方法可以将材质中保存的无用属性剔除,在看了...
  • Unity项目开发过程中,美术经常会通过删除prefab的方法来删除自己不想要的资源,但是他们删除prefab后往往并不会去管prefab引用的资源,所以随着项目的进行,Resource文件夹会越变越大,这个工具可以通过扫描...
  • 我们的游戏制作完发布出去提供给玩家,为了给玩家带来更好的游戏体验,要做各种的优化以及设计,首先,游戏资源的加载就是一个非常重要的方面(尤其是网页游戏)。由于我们的游戏资源比较大,不能一下全部加载出来,...
  • 转载自 : Unity3D内存释放 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大.这里写下关于unity3d对于内存的管理与优化. Unity3D里有两种动态加载机制:一个是Resources.Load,另外一个通过...
  • 博主本来想自己写,有大大写的异常详细...在Unity3D中使用三维模型,主要依靠Mesh Filter组件载入多边形表面物体(polygon mesh),然后依靠Mesh Renderer组件将Mesh正确渲染出来。 内置基本3D模型 Unity3D内置有...
  • Unity3D 美术资源规范

    2014-11-26 17:58:42
    一.单位,比例统一  在建模型前先设置好单位,在同一场景中会用到的模型的单位设置必须一样,模型与模型之间的比例要正确,和程序的导入单位一致,即便到程序需要缩放也可以统一调整缩放比例。...
1 2 3 4 5 ... 15
收藏数 283
精华内容 113
关键字:

unity3d 删除无用资源