├── README.md ├── LICENSE └── ShaderVariantCollectionExporter.cs /README.md: -------------------------------------------------------------------------------- 1 | # ShaderVariantCollectionExporter 2 | 3 | ## Install 4 | 5 | Place directory into `Editor`. 6 | 7 | ## Usage 8 | 9 | Execute `Tools` | `Shader` | `Export ShaderVariantCollection` 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 NETWORM 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /ShaderVariantCollectionExporter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using UnityEngine; 7 | using UnityEditor; 8 | using UnityEditor.SceneManagement; 9 | using Debug = UnityEngine.Debug; 10 | 11 | [InitializeOnLoad] 12 | public static class ShaderVariantCollectionExporter 13 | { 14 | [MenuItem("Tools/Shader/Export ShaderVariantCollection")] 15 | private static void Export() 16 | { 17 | var dict = new Dictionary(); 18 | 19 | foreach (var assetBundleName in AssetDatabase.GetAllAssetBundleNames()) 20 | { 21 | string[] assetPaths = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleName); 22 | foreach (var dependency in AssetDatabase.GetDependencies(assetPaths, true)) 23 | { 24 | if (!dict.ContainsKey(dependency)) 25 | { 26 | dict.Add(dependency, true); 27 | } 28 | } 29 | } 30 | 31 | var di = new DirectoryInfo("Assets/Resources"); 32 | foreach (var fi in di.GetFiles("*", SearchOption.AllDirectories)) 33 | { 34 | if (fi.Extension == ".meta") 35 | { 36 | continue; 37 | } 38 | 39 | string assetPath = fi.FullName.Replace(Application.dataPath, "Assets"); 40 | foreach (var dependency in AssetDatabase.GetDependencies(assetPath, true)) 41 | { 42 | if (!dict.ContainsKey(dependency)) 43 | { 44 | dict.Add(dependency, true); 45 | } 46 | } 47 | } 48 | 49 | string[] scenes = (from scene in EditorBuildSettings.scenes 50 | where scene.enabled 51 | select scene.path).ToArray(); 52 | foreach (var dependency in AssetDatabase.GetDependencies(scenes, true)) 53 | { 54 | if (!dict.ContainsKey(dependency)) 55 | { 56 | dict.Add(dependency, true); 57 | } 58 | } 59 | 60 | var materials = new List(); 61 | var shaderDict = new Dictionary>(); 62 | foreach (var assetPath in dict.Keys) 63 | { 64 | var material = AssetDatabase.LoadAssetAtPath(assetPath); 65 | if (material != null) 66 | { 67 | if (material.shader != null) 68 | { 69 | if (!shaderDict.ContainsKey(material.shader)) 70 | { 71 | shaderDict.Add(material.shader, new List()); 72 | } 73 | 74 | if (!shaderDict[material.shader].Contains(material)) 75 | { 76 | shaderDict[material.shader].Add(material); 77 | } 78 | } 79 | 80 | if (!materials.Contains(material)) 81 | { 82 | materials.Add(material); 83 | } 84 | } 85 | } 86 | 87 | ProcessMaterials(materials); 88 | 89 | var sb = new System.Text.StringBuilder(); 90 | foreach (var kvp in shaderDict) 91 | { 92 | sb.AppendLine(kvp.Key + " " + kvp.Value.Count + " times"); 93 | 94 | if (kvp.Value.Count <= 5) 95 | { 96 | Debug.LogWarning("Shader: " + kvp.Key.name, kvp.Key); 97 | 98 | foreach (var m in kvp.Value) 99 | { 100 | Debug.Log(AssetDatabase.GetAssetPath(m), m); 101 | } 102 | } 103 | } 104 | 105 | Debug.Log(sb.ToString()); 106 | } 107 | 108 | static ShaderVariantCollectionExporter() 109 | { 110 | EditorApplication.update += EditorUpdate; 111 | } 112 | 113 | private static void EditorUpdate() 114 | { 115 | if (_isStarted && _elapsedTime.ElapsedMilliseconds >= WaitTimeBeforeSave) 116 | { 117 | Debug.Log(InvokeInternalStaticMethod(typeof(ShaderUtil), 118 | "GetCurrentShaderVariantCollectionVariantCount")); 119 | _elapsedTime.Stop(); 120 | _elapsedTime.Reset(); 121 | _isStarted = false; 122 | EditorApplication.isPlaying = false; 123 | InvokeInternalStaticMethod(typeof(ShaderUtil), "SaveCurrentShaderVariantCollection", 124 | ShaderVariantCollectionPath); 125 | Debug.Log( 126 | InvokeInternalStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionShaderCount")); 127 | } 128 | } 129 | 130 | private static void ProcessMaterials(List materials) 131 | { 132 | EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); 133 | InvokeInternalStaticMethod(typeof(ShaderUtil), "ClearCurrentShaderVariantCollection"); 134 | Debug.Log(InvokeInternalStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionShaderCount")); 135 | 136 | int totalMaterials = materials.Count; 137 | 138 | var camera = Camera.main; 139 | if (camera == null) 140 | { 141 | Debug.LogError("Main Camera didn't exist"); 142 | return; 143 | } 144 | 145 | float aspect = camera.aspect; 146 | 147 | float height = Mathf.Sqrt(totalMaterials / aspect) + 1; 148 | float width = Mathf.Sqrt(totalMaterials / aspect) * aspect + 1; 149 | 150 | float halfHeight = Mathf.CeilToInt(height / 2f); 151 | float halfWidth = Mathf.CeilToInt(width / 2f); 152 | 153 | camera.orthographic = true; 154 | camera.orthographicSize = halfHeight; 155 | camera.transform.position = new Vector3(0f, 0f, -10f); 156 | 157 | Selection.activeGameObject = camera.gameObject; 158 | EditorApplication.ExecuteMenuItem("GameObject/Align View to Selected"); 159 | 160 | int xMax = (int) (width - 1); 161 | 162 | int x = 0; 163 | int y = 0; 164 | 165 | for (int i = 0; i < materials.Count; i++) 166 | { 167 | var material = materials[i]; 168 | 169 | var position = new Vector3(x - halfWidth + 1f, y - halfHeight + 1f, 0f); 170 | CreateSphere(material, position, x, y, i); 171 | 172 | if (x == xMax) 173 | { 174 | x = 0; 175 | y++; 176 | } 177 | else 178 | { 179 | x++; 180 | } 181 | } 182 | 183 | _elapsedTime.Stop(); 184 | _elapsedTime.Reset(); 185 | _elapsedTime.Start(); 186 | _isStarted = true; 187 | } 188 | 189 | private static void CreateSphere(Material material, Vector3 position, int x, int y, int index) 190 | { 191 | var go = GameObject.CreatePrimitive(PrimitiveType.Sphere); 192 | go.GetComponent().material = material; 193 | go.transform.position = position; 194 | go.name = string.Format("Sphere_{0}|{1}_{2}|{3}", index, x, y, material.name); 195 | } 196 | 197 | private static object InvokeInternalStaticMethod(System.Type type, string method, params object[] parameters) 198 | { 199 | var methodInfo = type.GetMethod(method, BindingFlags.NonPublic | BindingFlags.Static); 200 | if (methodInfo == null) 201 | { 202 | Debug.LogError(string.Format("{0} method didn't exist", method)); 203 | return null; 204 | } 205 | 206 | return methodInfo.Invoke(null, parameters); 207 | } 208 | 209 | private static bool _isStarted; 210 | private static readonly Stopwatch _elapsedTime = new Stopwatch(); 211 | 212 | private const string ShaderVariantCollectionPath = "Assets/ShaderVariantCollection.shadervariants"; 213 | private const int WaitTimeBeforeSave = 1000; 214 | } 215 | --------------------------------------------------------------------------------