public class MeshLister : EditorWindow { [MenuItem("Tools/Mesh Lister")] static void Open() { GetWindow(); } struct Info { public Mesh mesh; public int subMeshes; public int triCount; public int total; public int occurences; public string file; }; Info[] infos; Vector2 scrollPosition; int totalTriCount; private void OnGUI() { if (GUILayout.Button("Refresh")) { Dictionary meshSet = new Dictionary(); MeshFilter[] meshFilters = FindObjectsOfType(); foreach (MeshFilter mf in meshFilters) if (meshSet.ContainsKey(mf.sharedMesh)) meshSet[mf.sharedMesh]++; else meshSet.Add(mf.sharedMesh, 1); SkinnedMeshRenderer[] skinnedMeshs = FindObjectsOfType(); foreach (SkinnedMeshRenderer skinned in skinnedMeshs) if (meshSet.ContainsKey(skinned.sharedMesh)) meshSet[skinned.sharedMesh]++; else meshSet.Add(skinned.sharedMesh, 1); ParticleSystemRenderer[] particles = FindObjectsOfType(); foreach (ParticleSystemRenderer fx in particles) if (fx.renderMode == ParticleSystemRenderMode.Mesh && fx.mesh != null) if (meshSet.ContainsKey(fx.mesh)) meshSet[fx.mesh]++; else meshSet.Add(fx.mesh, 1); Mesh[] meshes = new Mesh[meshSet.Keys.Count]; meshSet.Keys.CopyTo(meshes, 0); totalTriCount = 0; infos = new Info[meshes.Length]; for (int i = 0; i < meshes.Length; i++) { infos[i].mesh = meshes[i]; infos[i].occurences = meshSet[meshes[i]]; infos[i].file = string.Empty; if (meshes[i] == null) continue; infos[i].subMeshes = meshes[i].subMeshCount; int count = 0; for (int j = 0; j < infos[i].subMeshes; j++) count += meshes[i].GetTriangles(j).Length / 3; infos[i].triCount = count; string path = AssetDatabase.GetAssetPath(meshes[i]); infos[i].file = System.IO.Path.GetFileName(path); infos[i].total = infos[i].triCount * infos[i].occurences; totalTriCount += infos[i].total; } } EditorGUILayout.BeginHorizontal(); GUILayout.Label("Mesh", EditorStyles.boldLabel, GUILayout.Width(200)); if (GUILayout.Button("File", EditorStyles.boldLabel)) Array.Sort(infos, (lhs, rhs) => { return lhs.file.CompareTo(rhs.file); }); if (GUILayout.Button("Occurences", EditorStyles.boldLabel, GUILayout.Width(80))) Array.Sort(infos, (lhs, rhs) => { return rhs.occurences - lhs.occurences; }); if (GUILayout.Button("SubMeshes", EditorStyles.boldLabel, GUILayout.Width(80))) Array.Sort(infos, (lhs, rhs) => { return rhs.subMeshes - lhs.subMeshes; }); if (GUILayout.Button("Triangles", EditorStyles.boldLabel, GUILayout.Width(80))) Array.Sort(infos, (lhs, rhs) => { return rhs.triCount - lhs.triCount; }); if (GUILayout.Button("Total", EditorStyles.boldLabel, GUILayout.Width(80))) Array.Sort(infos, (lhs, rhs) => { return rhs.total - lhs.total; }); EditorGUILayout.EndHorizontal(); if (infos != null) { scrollPosition = GUILayout.BeginScrollView(scrollPosition); for (int i = 0; i < infos.Length; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.ObjectField(infos[i].mesh, typeof(Mesh), false, GUILayout.Width(200)); GUILayout.Label(infos[i].file); GUILayout.Label(infos[i].occurences.ToString(), GUILayout.Width(80)); GUILayout.Label(infos[i].subMeshes.ToString(), GUILayout.Width(80)); GUILayout.Label(infos[i].triCount.ToString(), GUILayout.Width(80)); GUILayout.Label(infos[i].total.ToString(), GUILayout.Width(80)); EditorGUILayout.EndHorizontal(); } GUILayout.EndScrollView(); GUILayout.Label(string.Format("Total triangle count: {0}", totalTriCount)); } } }