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;});
}
}
Unity3d删除无用的美术资源的更多相关文章
- android删除无用资源文件的python脚本
随着android项目的进行,如果没有及时删除无用的资源时安装包会越来越大,是时候整理一下废弃资源缩小压缩包了,少年! 其实判断一个资源(drawable,layout)是否没有被使用很简单,文件名( ...
- Android lint 删除无用图片文件和配置文件
Android lint 删除无用.冗余的 配置文件和 图片资源 转载请注明 http://blog.csdn.net/aaawqqq?viewmode=contents Android项 ...
- iOS ipa包瘦身------删除无用图片资源
随着客户端业务的增多和业务的更新,App包大小越来越大,优化包大小是迫在眉睫,客户端需要优化的地方也有很多,本期主要讲如何查找无用图片并且删除无用图片的方法. 方案1:(暴力方法) ...
- Oracle监控用户索引使用情况,删除无用索引
监控当前业务用户索引 一段时间后查询从未被使用的索引,删除无用索引 停止监控索引 1. 监控当前用户所有索引 得到监控所有索引的语句: select 'alter index ' || index_n ...
- Win7系统下彻底删除无用服务的方法
win7系统下中有非常多的服务项,用户来满足不同行业用户间的所有需求,系统服务也是执行指定系统功能的程序,许多情况下我们想要运行软件或执行外接设备都无法离开系统服务,但并非所有系统服务都是我们用到的, ...
- Linux - 修改内核启动顺序及删除无用内核
现象: CentOS7开机启动界面显示多个内核选项 原因: 正常情况下,有两个启动项,一个是"正常启动",另一个是"救援模式启动"(rescue). 如果启动项 ...
- docker 删除无用的镜像文件的命令小计
df -h 查看当前服务器的内存情况 docker system prune 删除无用镜像文件命令 执行ok之后,再次查看内存情况.
- ubuntu的boot分区报警,删除无用内核文件。
1. 查看当前使用内核:uname -r4.4.0-97-generic 2. 查看安装的内核dpkg --list 'linux-image*' 3. 删除旧内核sudo apt-get remov ...
- centos7 选定默认启动内核,及删除无用内核
#使用cat /boot/grub2/grub.cfg |grep menuentry 查看系统可用内核 [root@bigapp-slave27 ~]# cat /boot/grub2/grub.c ...
随机推荐
- [ucgui] 对话框4——模式消息窗口
>_<" 这里实现点击灰色窗口的按钮出现一个模式消息窗口,点击OK之后才能再聚焦到灰窗口:点击灰窗口除了按钮的地方,弹出一个非模式窗口.
- spring mvc 配置对静态资源的访问
在spring mvc的配置文件中做如下配置: 1. <?xml version="1.0" encoding="UTF-8"?> <bean ...
- 微软 PowerShell Script Explorer 满血复活,正式发布
一年前的今天,微软在其Windows PowerShell官方博客声明中止 ‘Script Explorer’ 应用程序的开发. 一年后的今天,微软为其Script Explorer注入了新的生命.一 ...
- servlet web文件上传
web文件上传也是一种POST方式,特别之处在于,需设置FORM的enctype属性为multipart/form-data. 并且需要使用文件域. servlet的代码比较关键是这几句: // 使用 ...
- JProfiler8 注册码序列号
JProfiler_SN_8_x.txt 按默认选择"Single or evaluation license" Name 和 Company 随意 --------------- ...
- 连接数据库——模拟ATM机查、存、取、开户功能
1.界面:包含开户.查询.存款.取款.功能 package com.bank.test; /** * * @author Administrator *界面类 */ public class Jiem ...
- (转载)新手如何正确理解GitHub中“PR(pull request)”中的意思
我从知乎看到的两个答案,分别从实际意义以及语言学角度告诉你改怎么理解PR,很简洁,这个理解非常棒,会解决新手刚看到PR(pull request)这个词时的困惑. 实际意义: 有一个仓库,叫R ...
- asynchttpClient框架关于多文件批量上传的问题,改用xUtil
RequestParams params = new RequestParams(); params.add("ordernum",ordernum); params.add(&q ...
- 远哥教你MuleESB系列视频教程
远哥教你MuleESB系列视频课程介绍(共11个视频) 1.Mule ESB介绍 2.社区版/企业版的区别和安装 3.MuleESB快速入门,以及MEL和Message结构 4.官方例子讲解( ...
- GTD时间管理(2)---管理收集箱
通过上面一篇文章,相信大家对GTD收集有了原理大致的了解,如果大家对收集不是很了解,可以去看一下. 当我们收集到很多想法和事情之后,在晚会的时候必须要清空收集箱,否则收集箱会堆积如山,最终收集箱成了垃 ...