Пример #1
0
        /// <summary>
        /// 按shader进行剔除
        /// </summary>
        /// <returns>如果需要放弃本次处理,返回true</returns>
        private bool DoExcludeShader(ShaderKeywordConfig config, Shader currentShader)
        {
            Shader[] e = config.ExcludeShader;
            if (e == null)
            {
                return(false);
            }

            for (int i = 0; i < e.Length; i++)
            {
                if (e[i] == currentShader)
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #2
0
        private void DoCreate(BuildTarget materialBuildTarget)
        {
            if (exceptionSB == null)
            {
                exceptionSB = new StringBuilder();
            }
            else
            {
                exceptionSB.Clear();
            }

            //计时开始
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();

            if (!writeToFile)
            {
                ShaderVariantCollection svc = new ShaderVariantCollection();
                currentSVC = svc;
                svcToShow  = svc;
                AssetDatabase.CreateAsset(svc, m_svcPath);
            }

            currentConfig = excludeConfig;

            isCreating     = true;
            dataDictionary = new Dictionary <Shader, HashSet <string> >();

            int totalMaterialsCount        = 0;
            int removedFBXCount            = 0;
            int removedErrorMaterialsCount = 0;
            int finalMaterialsCount        = 0;

            //Resources目录下的所有材质
            string[] guidMats = AssetDatabase.FindAssets("t:Material", new string[] { m_materialsPath });
            totalMaterialsCount = guidMats.Length;

            List <string> assetNameList = new List <string>();

            //移除空材质、错误材质和嵌入材质附带的FBX文件
            for (int i = 0; i < guidMats.Length; i++)
            {
                EditorUtility.DisplayProgressBar("正在扫描材质", i + " / " + guidMats.Length, i * 1.0f / guidMats.Length);
                string an = AssetDatabase.GUIDToAssetPath(guidMats[i]);
                if (string.Equals(Path.GetExtension(an), ".fbx", StringComparison.OrdinalIgnoreCase))
                {
                    removedFBXCount++;
                    continue;
                }
                Material mat = (Material)AssetDatabase.LoadAssetAtPath(an, typeof(Material));
                if (mat == null || mat.shader == null)
                {
                    removedErrorMaterialsCount++;
                    continue;
                }
                assetNameList.Add(an);
#if DEBUG_ON
                Debug.Log("Add: " + an);
#endif
            }

            // Create the array of bundle build details.
            AssetBundleBuild buildMap = new AssetBundleBuild
            {
                assetBundleName = abName,
                assetNames      = assetNameList.ToArray(),
            };

            AssetBundleBuild[] buildMapArray = new AssetBundleBuild[1];
            buildMapArray[0] = buildMap;
            EditorUtility.ClearProgressBar();
            finalMaterialsCount = buildMap.assetNames.Length;

            if (!Directory.Exists(m_tempPath))
            {
                Directory.CreateDirectory(m_tempPath);
            }
            BuildPipeline.BuildAssetBundles(m_tempPath, buildMapArray, BuildAssetBundleOptions.None, materialBuildTarget);

            if (writeToFile)
            {
                //StreamWriter第二个参数为false覆盖现有文件,为true则把文本追加到文件末尾
                using (StreamWriter file = new StreamWriter(m_txtPath, false))
                {
                    foreach (KeyValuePair <Shader, HashSet <string> > kvp in dataDictionary)
                    {
                        file.WriteLine("Shader: " + kvp.Key.name);
                        HashSet <string> v = kvp.Value;
                        foreach (string kws in v)
                        {
                            file.WriteLine(kws);
                        }
                    }

                    file.Close();
                }
            }

            if (autoDeleteTempFolder)
            {
#if DEBUG_ON
                Debug.Log("Delete temp bundle");
#endif
                DeleteTempFolder();
            }

            //计时结束
            stopwatch.Stop();
            TimeSpan timespan = stopwatch.Elapsed;

            isCreating    = false;
            currentSVC    = null;
            currentConfig = null;

            ClearOutput();
            outputSB.AppendLine("创建完成,耗时: " + timespan.Hours + "h," + timespan.Minutes + "m," + timespan.Seconds + "s");
            outputSB.AppendLine("已扫描材质数量: " + totalMaterialsCount);
            outputSB.AppendLine("移除FBX数量: " + removedFBXCount);
            outputSB.AppendLine("移除错误材质数量: " + removedErrorMaterialsCount);
            outputSB.AppendLine("最终材质数量: " + finalMaterialsCount);
            if (!writeToFile)
            {
                ShowSVCInfo();
            }
            AssetDatabase.SaveAssets();
        }
Пример #3
0
        /// <inheritdoc />
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> data)
        {
            if (!ShaderVariantCollectionGenerator3.IsCreating)
            {
                return;
            }
#if DEBUG_ON
            Debug.Log("SVCG_ShaderPreprocessor.OnProcessShader(" + shader.name + ")");
#endif
            ShaderVariantCollection svc = ShaderVariantCollectionGenerator3.CurrentSVC;
            if (!ShaderVariantCollectionGenerator3.WillWriteToFile && svc == null)
            {
                return;
            }

            //处理剔除配置
            if (ShaderVariantCollectionGenerator3.CurrentConfig != null)
            {
                EditorUtility.DisplayProgressBar("正在执行剔除", $"Shader: {shader.name}", 0);
                ShaderKeywordConfig config = ShaderVariantCollectionGenerator3.CurrentConfig;
                if (DoExcludeShader(config, shader))
                {
                    return;
                }
                EditorUtility.DisplayProgressBar("正在执行剔除", $"Shader: {shader.name}", 0.3333f);
                if (DoExclude(config.GetGlobalConfig(), snippet, data))
                {
                    return;
                }
                EditorUtility.DisplayProgressBar("正在执行剔除", $"Shader: {shader.name}", 0.6666f);
                if (DoExclude(config.GetConfigOfShader(shader), snippet, data))
                {
                    return;
                }
                EditorUtility.DisplayProgressBar("正在执行剔除", $"Shader: {shader.name}", 1);
            }

            for (int i = 0; i < data.Count; i++)
            {
                EditorUtility.DisplayProgressBar("正在处理变体", $"Shader: {shader.name}, data: {i}/{data.Count}", (float)i / data.Count);

                ShaderKeyword[] kws = data[i].shaderKeywordSet.GetShaderKeywords();

                if (ShaderVariantCollectionGenerator3.WillWriteToFile)
                {
                    string[] strKWs = new string[kws.Length + 1];
                    strKWs[0] = ((int)snippet.passType).ToString();
                    for (int j = 1; j < kws.Length + 1; j++)
                    {
#if UNITY_2019_3_OR_NEWER
                        strKWs[j] = ShaderKeyword.GetKeywordName(shader, kws[j - 1]);
#else
                        strKWs[j] = kws[j - 1].GetKeywordName();
#endif
                    }

                    HashSet <string> d = null;
                    if (ShaderVariantCollectionGenerator3.DataDictionary.TryGetValue(shader, out d))
                    {
                        d.Add(DebugUtil.LogString(strKWs));
                    }
                    else
                    {
                        d = new HashSet <string>();
                        d.Add(DebugUtil.LogString(strKWs));
                        ShaderVariantCollectionGenerator3.DataDictionary.Add(shader, d);
                    }
#if DEBUG_ON
                    Debug.Log("file.Add(" + DebugUtil.LogString(strKWs) + ")");
#endif
                }
                else
                {
                    string[] strKWs = new string[kws.Length];
                    for (int j = 0; j < kws.Length; j++)
                    {
#if UNITY_2019_3_OR_NEWER
                        strKWs[j] = ShaderKeyword.GetKeywordName(shader, kws[j]);
#else
                        strKWs[j] = kws[j].GetKeywordName();
#endif
                    }
#if DEBUG_ON
                    Debug.Log("svc.Add(" + shader + ", " + snippet.passType + ", " + DebugUtil.LogString(strKWs) + ")");
#endif
                    if (ShaderVariantCollectionGenerator3.StopOnException)
                    {
                        svc.Add(new ShaderVariantCollection.ShaderVariant(shader, snippet.passType, strKWs));
                    }
                    else
                    {
                        //不使用构造函数可以避免调用 ShaderVariantCollection.ShaderVariant.CheckShaderVariant
                        //它将耗费大量时间来判断输入数据是否存在异常
                        ShaderVariantCollection.ShaderVariant sv = new ShaderVariantCollection.ShaderVariant();
                        sv.shader   = shader;
                        sv.passType = snippet.passType;
                        sv.keywords = strKWs;
                        svc.Add(sv);
                    }
                }
            }

            //实际打包时不编译shader变体,仅收集信息,大幅优化执行时间
            data.Clear();
        }
Пример #4
0
        void OnGUI()
        {
            GUILayout.Space(5);

            GUIStyle logoFont = new GUIStyle(EditorStyles.label)
            {
                alignment = TextAnchor.MiddleCenter,
                fontSize  = 20
            };

            GUILayout.Label("ShaderVariantCollectionGenerator", logoFont);

            GUILayout.Space(10);

            GUILayout.Label("扫描材质路径(可以拖入文件夹自动获取)");
            EditorGUILayout.BeginHorizontal();
            {
                EditorGUI.BeginChangeCheck();
                pathObj = EditorGUILayout.ObjectField(pathObj, typeof(UnityEngine.Object), false, GUILayout.Width(110));
                if (EditorGUI.EndChangeCheck())
                {
                    m_materialsPath = AssetDatabase.GetAssetPath(pathObj);
                    //判断是否为斜杠结尾,搜索的文件夹不能用斜杠结尾
                    if (m_materialsPath.EndsWith("/"))
                    {
                        m_materialsPath = m_materialsPath.Remove(m_materialsPath.Length - 2, 1);
                    }
                    pathObj = null;
                }

                m_materialsPath = EditorGUILayout.TextField(m_materialsPath);
            }
            EditorGUILayout.EndHorizontal();
            GUILayout.Space(10);

            GUILayout.Label("生成变体文件路径");
            m_svcPath = EditorGUILayout.TextField(m_svcPath);
            svcToShow = (ShaderVariantCollection)EditorGUILayout.ObjectField("ShaderVariantCollection", svcToShow, typeof(ShaderVariantCollection), false);
            GUILayout.Space(10);

            GUILayout.Label("剔除配置文件路径");
            configPath    = EditorGUILayout.TextField(configPath);
            excludeConfig = (ShaderKeywordConfig)EditorGUILayout.ObjectField("ExcludeKeywordConfig", excludeConfig, typeof(ShaderKeywordConfig), false);
            GUILayout.Space(10);

            GUILayout.Label("临时文件夹路径,不能用斜杠结尾");
            m_tempPath = EditorGUILayout.TextField(m_tempPath);
            GUILayout.Space(10);

            GUILayout.Label("文本文件路径");
            m_txtPath = EditorGUILayout.TextField(m_txtPath);
            GUILayout.Space(10);

            m_materialBuildTarget = (BuildTarget)EditorGUILayout.EnumPopup("MaterialBuildTarget", m_materialBuildTarget);
            GUILayout.Space(10);

            stopOnException      = EditorGUILayout.ToggleLeft("异常时中断执行,严重增加运行时间", stopOnException);
            autoDeleteTempFolder = EditorGUILayout.ToggleLeft("自动清除临时文件夹", autoDeleteTempFolder);
            writeToFile          = EditorGUILayout.ToggleLeft("结果写入文本文件,不生成变体", writeToFile);

            const int buttonHeight = 40;

            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button("自动获取 KeywordConfig", GUILayout.Height(buttonHeight)))
                {
                    excludeConfig = (ShaderKeywordConfig)AssetDatabase.LoadAssetAtPath(configPath, typeof(ShaderKeywordConfig));
                    if (excludeConfig == null)
                    {
                        EditorUtility.DisplayDialog("SVCG", "文件不存在或无法加载", "哦");
                    }
                }
                if (GUILayout.Button("创建 KeywordConfig", GUILayout.Height(buttonHeight)))
                {
                    if (File.Exists(configPath))
                    {
                        if (!EditorUtility.DisplayDialog("SVCG", "文件已存在,是否覆盖?", "是", "否"))
                        {
                            return;
                        }
                    }
                    excludeConfig = CreateInstance <ShaderKeywordConfig>();
                    AssetDatabase.CreateAsset(excludeConfig, configPath);
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button("自动获取 SVC", GUILayout.Height(buttonHeight)))
                {
                    svcToShow = (ShaderVariantCollection)AssetDatabase.LoadAssetAtPath(m_svcPath, typeof(ShaderVariantCollection));
                    if (svcToShow == null)
                    {
                        EditorUtility.DisplayDialog("SVCG", "文件不存在或无法加载", "哦");
                    }
                }
                if (GUILayout.Button("覆盖选择 SVC", GUILayout.Height(buttonHeight)))
                {
                    if (svcToShow != null)
                    {
                        m_svcPath = AssetDatabase.GetAssetPath(svcToShow);
                    }
                }
                if (GUILayout.Button("显示SVC信息", GUILayout.Height(buttonHeight)))
                {
                    ClearOutput();
                    ShowSVCInfo();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button("清除临时文件", GUILayout.Height(buttonHeight)))
                {
                    DeleteTempFile();
                }
                if (GUILayout.Button("清除临时文件夹", GUILayout.Height(buttonHeight)))
                {
                    DeleteTempFolder();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            {
                Color defaultColor = GUI.backgroundColor;
                GUI.backgroundColor = Color.green;
                if (GUILayout.Button("收集变体", GUILayout.Height(buttonHeight)))
                {
                    ClearOutput();
                    outputSB.AppendLine("收集中...");
                    DoCreate(m_materialBuildTarget);
                }
                GUI.backgroundColor = defaultColor;

                if (GUILayout.Button("从文本文件写入变体", GUILayout.Height(buttonHeight)))
                {
                    ShaderVariantCollection svc = new ShaderVariantCollection();
                    svcToShow = svc;
                    AssetDatabase.CreateAsset(svc, m_svcPath);
                    ReadSVCDataAndAdd(svcToShow);
                }
            }
            EditorGUILayout.EndHorizontal();


            //使用这种方式禁止交互
            GUILayout.Label(outputSB.ToString(), EditorStyles.textArea, GUILayout.Height(120));

            //_guiDebug();
        }