Created
February 13, 2026 16:10
-
-
Save aobond2/c9cb2f4225a9b23c30bd251916b6581b to your computer and use it in GitHub Desktop.
Check all object in a scene, get info on triangle count, texture size, and memory size. Then enable sorting based on these.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Generic; | |
| using System.Linq; | |
| using UnityEditor; | |
| using UnityEngine; | |
| namespace Editor | |
| { | |
| public class AssetAuditorWindow : EditorWindow | |
| { | |
| private Vector2 _scrollPos; | |
| private List<AuditResult> _results = new List<AuditResult>(); | |
| // Enum to keep track sorting state | |
| private enum SortBy { Name, Tris, TextureRes, MemorySize } | |
| private SortBy currentSort = SortBy.Tris; | |
| private bool ascending = false; | |
| [MenuItem("Tools/Asset Auditor")] | |
| public static void ShowWindow() => GetWindow<AssetAuditorWindow>("Asset Auditor"); | |
| private void OnGUI() | |
| { | |
| GUILayout.Label("Scene Performance Auditor", EditorStyles.boldLabel); | |
| if (GUILayout.Button("Scan Current Scene", GUILayout.Height(30))) | |
| { | |
| PerformAudit(); | |
| } | |
| EditorGUILayout.Space(); | |
| // Header | |
| EditorGUILayout.BeginHorizontal((EditorStyles.helpBox)); | |
| if (GUILayout.Button("Object Name", EditorStyles.toolbarButton, GUILayout.Width(200))) SetSort(SortBy.Name); | |
| if (GUILayout.Button("Tris", EditorStyles.toolbarButton, GUILayout.Width(70))) SetSort(SortBy.Tris); | |
| if (GUILayout.Button("Texture Res", EditorStyles.toolbarButton, GUILayout.Width(100))) SetSort(SortBy.TextureRes); | |
| if (GUILayout.Button("VRAM", EditorStyles.toolbarButton, GUILayout.Width(80))) SetSort(SortBy.MemorySize); | |
| EditorGUILayout.EndHorizontal(); | |
| // Result List | |
| _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); | |
| foreach (var result in _results) | |
| { | |
| EditorGUILayout.BeginHorizontal("box"); | |
| GUILayout.Label(result.Name, GUILayout.Width(200)); | |
| //Color code high poly counts | |
| GUI.color = result.Tris > 5000 ? Color.red : Color.white; | |
| GUILayout.Label(result.Tris.ToString(), GUILayout.Width(70)); | |
| GUI.color = Color.white; | |
| GUILayout.Label(result.TEXRes, GUILayout.Width(100)); | |
| // Display memory in MB | |
| string memDisplay = (result.MemSize / (1024f * 1024f)).ToString("F2") + " MB"; | |
| GUI.color = result.MemSize > 1000000 ? Color.yellow : Color.white; // If more than 1 MB | |
| GUILayout.Label(memDisplay, GUILayout.Width(80)); | |
| GUI.color = Color.white; | |
| if (GUILayout.Button("Select", GUILayout.Width(60))) | |
| { | |
| Selection.activeGameObject = result.Go; | |
| EditorGUIUtility.PingObject(result.Go); | |
| } | |
| EditorGUILayout.EndHorizontal(); | |
| } | |
| EditorGUILayout.EndScrollView(); | |
| } | |
| void SetSort(SortBy mode) | |
| { | |
| if (currentSort == mode) ascending = !ascending; | |
| else | |
| { | |
| currentSort = mode; | |
| ascending = false; | |
| } | |
| SortResults(); | |
| } | |
| void SortResults() | |
| { | |
| switch (currentSort) | |
| { | |
| case SortBy.Name: _results = ascending ? _results.OrderBy(r => r.Name).ToList() : _results.OrderByDescending(r => r.Name).ToList(); break; | |
| case SortBy.Tris: _results = ascending ? _results.OrderBy(r => r.Tris).ToList() : _results.OrderByDescending(r => r.Tris).ToList(); break; | |
| case SortBy.TextureRes: _results = ascending ? _results.OrderBy(r => r.TEXHeight * r.TEXWidth).ToList() : _results.OrderByDescending(r => r.TEXHeight * r.TEXWidth).ToList(); break; | |
| case SortBy.MemorySize: _results = ascending ? _results.OrderBy(r => r.MemSize).ToList() : _results.OrderByDescending(r => r.MemSize).ToList(); break; | |
| } | |
| } | |
| void PerformAudit() | |
| { | |
| _results.Clear(); | |
| MeshFilter[] meshFilters = FindObjectsByType<MeshFilter>(FindObjectsSortMode.None); | |
| foreach (var meshFilter in meshFilters) | |
| { | |
| int triCount = meshFilter.sharedMesh ? meshFilter.sharedMesh.triangles.Length / 3 : 0; | |
| string texInfo = "None"; | |
| long memory = 0; | |
| int w = 0, h = 0; | |
| Renderer renderer = meshFilter.gameObject.GetComponent<Renderer>(); | |
| if (renderer != null && meshFilter.GetComponent<Renderer>()?.sharedMaterial?.mainTexture != null) | |
| { | |
| var tex = meshFilter.GetComponent<Renderer>().sharedMaterial.mainTexture; | |
| w = tex.width; | |
| h = tex.height; | |
| texInfo = $"{w}x{h}"; | |
| // Get actual compress size in bytes | |
| memory = UnityEngine.Profiling.Profiler.GetRuntimeMemorySizeLong(tex); | |
| } | |
| _results.Add(new AuditResult | |
| { | |
| Name = meshFilter.name, | |
| Tris = triCount, | |
| TEXRes = texInfo, | |
| TEXWidth = w, | |
| TEXHeight = h, | |
| MemSize = memory, | |
| Go = meshFilter.gameObject, | |
| }); | |
| } | |
| // Sort by triangles descending | |
| _results = _results.OrderByDescending(r => r.Tris).ToList(); | |
| } | |
| struct AuditResult | |
| { | |
| public string Name; | |
| public int Tris; | |
| public string TEXRes; | |
| public int TEXWidth; | |
| public int TEXHeight; | |
| public long MemSize; | |
| public GameObject Go; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment