Unity3D實用指令碼(二)—— 檢查場景中用到的資源
在專案的開發過程中,經常需要檢查場景中所用到的資源,例如Textures,Materials,Meshs等。
今天來實現如圖所示的資源檢查功能。
程式碼如下:
// Resource Checker // (c) 2012 Simon Oliver / HandCircus / [email protected] // Public domain, do with whatever you like, commercial or not // This comes with no warranty, use at your own risk! // https://github.com/handcircus/Unity-Resource-Checker using System.Linq; using UnityEngine; using UnityEditor; using System.Collections.Generic; public class 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 TextureDetails() { } }; public class MaterialDetails { public Material material; public List<Renderer> FoundInRenderers=new List<Renderer>(); public MaterialDetails() { } }; public class MeshDetails { public Mesh mesh; public List<MeshFilter> FoundInMeshFilters=new List<MeshFilter>(); public List<SkinnedMeshRenderer> FoundInSkinnedMeshRenderer=new List<SkinnedMeshRenderer>(); public MeshDetails() { } }; public class 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 ("Custom/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) { 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; //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 } 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 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 (); 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; } 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(); 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; 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); ActiveTextures.Add(tTextureDetail); } } //if the texture was downloaded, it won't be included in the editor dependencies if (tMaterial.mainTexture != null && !dependencies.Contains(tMaterial.mainTexture)) { var tTextureDetail = GetTextureDetail(tMaterial.mainTexture, tMaterial, tMaterialDetails); ActiveTextures.Add(tTextureDetail); } } 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;}); } private TextureDetails GetTextureDetail(Texture tTexture, Material tMaterial, MaterialDetails tMaterialDetails) { 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; } tTextureDetails.FoundInMaterials.Add(tMaterial); foreach (Renderer renderer in tMaterialDetails.FoundInRenderers) { if (!tTextureDetails.FoundInRenderers.Contains(renderer)) tTextureDetails.FoundInRenderers.Add(renderer); } return tTextureDetails; } }
相關推薦
Unity3D實用指令碼(二)—— 檢查場景中用到的資源
在專案的開發過程中,經常需要檢查場景中所用到的資源,例如Textures,Materials,Meshs等。 今天來實現如圖所示的資源檢查功能。 程式碼如下: // Resource Checker // (c) 2012 Simon Oliver / HandCirc
iptables實用教程(二):管理鏈和策略
否則 命令顯示 accept 目的 number cep 存在 當前 末尾 概念和原理請參考上一篇文章“iptables實用教程(一)”。 本文講解如果管理iptables中的鏈和策略。 下面的代碼格式中,下劃線表示是一個占位符,需要根據實際情況輸入參數,不帶下劃線的表示是
Nginx實用教程(二):配置文件入門
affinity type 服務 源碼編譯 設置時間 shutdown ber 可用 控制指令 Nginx配置文件結構 nginx配置文件由指令(directive)組成,指令分為兩種形式,簡單指令和區塊指令。 一條簡單指令由指令名、參數和結尾的分號(;)組成,例如:
前端開發框架總結之Angular實用技巧(二)
前端開發框架總結之Angular實用技巧(二) 上文講了Angular自
java調Python指令碼(二):java調Python亂碼問題
java調Python返回結果出現亂碼解決: Python指令碼編碼格式已經用了utf-8,但是返回還是亂碼,說明是java這邊傳過去編碼有問題。 1、Python編碼格式: 2、一般我們中文文字編碼格式常用的有:UTF-8,GBK,GB2312。分別試一下就知道了:
動態記憶體分配實用案例(二)之複製字串
用動態分配記憶體製作一個字串的一份拷貝。注意:呼叫程式應該負責檢查這塊記憶體是否分配成功,這樣做允許程式以任何它所希望的方式對錯誤作出反應。 #nclude <stdlib.h> #include <string.h> char * strdup
床頭筆記之Python程式設計實用函式(二)
python字典dict排序與sorted函式 sorted(iterable[, cmp[, key[, reverse]]]) 引數說明: iterable – 可迭代物件。 cmp --比較的函式,這個具有兩個引數,引數的值都是從可迭代物件中取出,此函
JAVA實用操作(二)安裝旗艦版IDEA(破解版)
第二步:雙擊已下載檔案,進行開始安裝; 點選 next 繼續ing… 選擇適合本機的64位(32位)版本,點選next 繼續… 選擇預設繼續… 等待安裝完成…next 繼續ing… 以上操作就完成了ideal的安裝了 ~~~ 接下來就是實現解析工
如何編寫一個優雅的Shell指令碼(二)
簡介 繼上一篇,本文主要描述一個shell指令碼的基本組成 公共模組 ## 自定義寫日誌函式 function writelog() { echo "[`date -d '%Y-%m-%d %H:%M:%S'`][$$]: $1" |tess -a $tmplogf
JVM實用引數(二)引數分類和即時(JIT)編譯器診斷
在這個系列的第二部分,我來介紹一下HotSpot JVM提供的不同類別的引數。我同樣會討論一些關於JIT編譯器診斷的有趣引數。 JVM 引數分類 HotSpot JVM 提供了三類引數。第一類包括了標準引數。顧名思義,標準引數中包括功能和輸出的引數都是很穩定的,很可能在將來的JVM版本中不會
Linux系統下製作服務啟動指令碼(二)
上一篇部落格介紹了在/etc/init.d目錄下製作應用服務啟動和停止指令碼,其實在/usr/bin目錄下也可以製作這種指令碼,不過一般不推薦這種方式,先來看一下是怎麼製作的: vim編寫指令碼start.sh,將指令碼複製到/usr/bin目錄下,去掉字尾名 然後進入任何目
自動化測試工具AutoRunner之錄製指令碼(二)
這一篇主要講一下使用AutoRunner錄製指令碼的方法 一、建立專案: 建立專案的方式有兩種: 1、在專案區單擊滑鼠右鍵,彈出建立專案選單。 2、選中“ 新建專案”,開啟“新建專案”彈窗。 3、 輸入“專案名稱”,此處有兩個選項,我們以“不
ant自動打包指令碼(二)
融合SDK ant自動打包指令碼,可以迴圈打包,採用源工程(主工程)和依賴庫的形式 <?xml version="1.0" encoding="UTF-8"?> <project name="AndroidProjectBuild" default="bu
建立一個簡單gradle指令碼(二)
update time:2019-1-10 Author:要你命三千又三千 type: 學習筆記 文章目錄 問題一:如何是用gradle 搭建的環境建立一個簡單的Gradle指令碼 問題二:gradle Wrapp
OGRE的材質指令碼 (二)
Texture_unit 紋理單元我們在PASS渲染通道處已經進行了一次整體的渲染環境設定,然而,在每個紋理單元,我們還可以對單獨的紋理進行渲染屬性設定。 texture_alias 設定一個紋理的別名,類似於技術的別名。格式: texture_alias 紋理別名預設該別名
Android中的MVVM架構設計-實用篇(二)
速度與激情7.jpg引言拖的時間夠久的了,趕緊來還債了...by the way...今天由於一些私人的關係,去了趟「大望路」的「小米體驗店」裡去體驗了一下,看到了剛剛釋出的的「小米8」,還有「小米8SE」,但是對我的感覺衝擊不是很大,不過 這兩部手機的速度肯定是沒得說的,價
spring boot 框架實用技巧(二)初次上手
1.現在我們就開始上手一下spring boot 框架的使用。 學習任何框架我覺得最簡單的方式就是從它的事例上學習,還有個前提就是你至少以前學習過至少一種框架的使用,這樣的話上手會很快。 首先如上圖import spring 的專案選中spring getting sta
Installshield2008 And 指令碼 (二)
利用Script來控制其安裝流程的時候。最基本的就是 OnBegin ---------> OnShowUI OnShowUI裡面為: OnFirstUIBefore -----------> OnMoveData ------------------>
Unity3D學習筆記(二):個體層次、絕對和局部坐標、V3平移旋轉
esp 返回 ESS coo his object spa cti dcom Directional Light:平行光源/方向性光源,用來模擬太陽光(角度只與旋轉角度有關,與位置無關) Point Light:點光源,用來模擬燈泡,向四周發散光源 Spotlight:錐光
LoadRunner11錄製APP指令碼(二)***利用WireShake進行抓包
前提: 1、安裝WireShark。在安裝WireShark過程中,會提示是否安裝WinPacp以及USBPacp。其中WinPacp必須安裝 2、電腦和手機必須處於同一網路