Example #1
0
        /// <summary>
        /// 检测所有损坏的预制体文件
        /// </summary>
        public static void CheckCorruptionPrefab()
        {
            // 获取所有的打包路径
            List <string> collectDirectorys = AssetBundleCollectorSettingData.GetAllCollectDirectory();

            if (collectDirectorys.Count == 0)
            {
                throw new Exception("打包路径列表不能为空");
            }

            // 获取所有资源列表
            int checkCount   = 0;
            int invalidCount = 0;

            string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Prefab, collectDirectorys.ToArray());
            foreach (string assetPath in findAssets)
            {
                UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
                if (prefab == null)
                {
                    invalidCount++;
                    Debug.LogError($"发现损坏预制件:{assetPath}");
                }
                EditorTools.DisplayProgressBar("检测预制件文件是否损坏", ++checkCount, findAssets.Length);
            }
            EditorTools.ClearProgressBar();

            if (invalidCount == 0)
            {
                Debug.Log($"没有发现损坏预制件");
            }
        }
        /// <summary>
        /// 拷贝补丁文件到补丁包目录
        /// </summary>
        private void CopyPatchFiles(AssetBundleBuilder.BuildParametersContext buildParameters)
        {
            string packageDirectory = buildParameters.GetPackageDirectory();

            BuildLogger.Log($"开始拷贝补丁文件到补丁包目录:{packageDirectory}");

            // 拷贝Readme文件
            {
                string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{PatchDefine.ReadmeFileName}";
                string destPath   = $"{packageDirectory}/{PatchDefine.ReadmeFileName}";
                EditorTools.CopyFile(sourcePath, destPath, true);
                BuildLogger.Log($"拷贝Readme文件到:{destPath}");
            }

            // 拷贝PatchManifest文件
            {
                string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{PatchDefine.PatchManifestFileName}";
                string destPath   = $"{packageDirectory}/{PatchDefine.PatchManifestFileName}";
                EditorTools.CopyFile(sourcePath, destPath, true);
                BuildLogger.Log($"拷贝PatchManifest文件到:{destPath}");
            }

            // 拷贝UnityManifest序列化文件
            {
                string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{PatchDefine.UnityManifestFileName}";
                string destPath   = $"{packageDirectory}/{PatchDefine.UnityManifestFileName}";
                EditorTools.CopyFile(sourcePath, destPath, true);
                BuildLogger.Log($"拷贝UnityManifest文件到:{destPath}");
            }

            // 拷贝UnityManifest文本文件
            {
                string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{PatchDefine.UnityManifestFileName}.manifest";
                string destPath   = $"{packageDirectory}/{PatchDefine.UnityManifestFileName}.manifest";
                EditorTools.CopyFile(sourcePath, destPath, true);
            }

            // 拷贝所有补丁文件
            // 注意:拷贝的补丁文件都是需要玩家热更新的文件
            int           progressValue       = 0;
            PatchManifest patchManifest       = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory);
            int           patchFileTotalCount = patchManifest.BundleList.Count;

            foreach (var patchBundle in patchManifest.BundleList)
            {
                if (patchBundle.Version == buildParameters.Parameters.BuildVersion)
                {
                    string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{patchBundle.BundleName}";
                    string destPath   = $"{packageDirectory}/{patchBundle.Hash}";
                    EditorTools.CopyFile(sourcePath, destPath, true);
                    BuildLogger.Log($"拷贝补丁文件到补丁包:{patchBundle.BundleName}");
                    EditorTools.DisplayProgressBar("拷贝补丁文件", ++progressValue, patchFileTotalCount);
                }
            }
            EditorTools.ClearProgressBar();
        }
        private static void CollectVariants(List <Material> materials, GameObject sceneGameObjects)
        {
            // 创建临时场景
            if (sceneGameObjects == null)
            {
                EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
            }
            else
            {
                EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
                GameObject.Instantiate <GameObject>(sceneGameObjects);
            }

            Camera camera = Camera.main;

            if (camera == null)
            {
                throw new System.Exception("Not found main camera.");
            }

            // 设置主相机
            float aspect         = camera.aspect;
            int   totalMaterials = materials.Count;
            float height         = Mathf.Sqrt(totalMaterials / aspect) + 1;
            float width          = Mathf.Sqrt(totalMaterials / aspect) * aspect + 1;
            float halfHeight     = Mathf.CeilToInt(height / 2f);
            float halfWidth      = Mathf.CeilToInt(width / 2f);

            camera.orthographic       = true;
            camera.orthographicSize   = halfHeight;
            camera.transform.position = new Vector3(0f, 0f, -10f);

            // 创建测试球体
            int xMax = (int)(width - 1);
            int x = 0, y = 0;
            int progressValue = 0;

            for (int i = 0; i < materials.Count; i++)
            {
                var material = materials[i];
                var position = new Vector3(x - halfWidth + 1f, y - halfHeight + 1f, 0f);
                CreateSphere(material, position, i);
                if (x == xMax)
                {
                    x = 0;
                    y++;
                }
                else
                {
                    x++;
                }
                EditorTools.DisplayProgressBar("测试所有材质球", ++progressValue, materials.Count);
            }
            EditorTools.ClearProgressBar();
        }
        /// <summary>
        /// 获取资源被依赖的集合
        /// </summary>
        /// <param name="searchAssetPath">资源路径</param>
        /// <param name="searchFolder">搜索的文件夹</param>
        private void FindReferenceInProject(string searchAssetPath, string searchFolder, EAssetSearchType serachType)
        {
            // 创建集合
            if (_collection == null)
            {
                _collection = new Dictionary <EAssetFileExtension, List <string> >();
                foreach (EAssetFileExtension value in Enum.GetValues(typeof(EAssetFileExtension)))
                {
                    _collection.Add(value, new List <string>());
                }
            }

            // 清空集合
            foreach (EAssetFileExtension value in Enum.GetValues(typeof(EAssetFileExtension)))
            {
                _collection[value].Clear();
            }

            // 查找引用
            int progressValue = 0;

            string[] findAssets = EditorTools.FindAssets(serachType, searchFolder);
            foreach (string assetPath in findAssets)
            {
                string[] dpends = AssetDatabase.GetDependencies(assetPath, _recursive);
                foreach (string name in dpends)
                {
                    if (name.Equals(assetPath))
                    {
                        continue;
                    }
                    if (name.Equals(searchAssetPath))
                    {
                        foreach (EAssetFileExtension value in Enum.GetValues(typeof(EAssetFileExtension)))
                        {
                            if (assetPath.EndsWith($".{value}"))
                            {
                                if (_collection[value].Contains(assetPath) == false)
                                {
                                    _collection[value].Add(assetPath);
                                    break;
                                }
                            }
                        }
                    }
                }
                EditorTools.DisplayProgressBar("正在搜索", ++progressValue, findAssets.Length);
            }
            EditorTools.ClearProgressBar();
        }
        /// <summary>
        /// 扫描所有资源
        /// </summary>
        public static Dictionary <string, List <ScanReport> > ScanAllAssets()
        {
            Dictionary <string, List <ScanReport> > result = new Dictionary <string, List <ScanReport> >();
            int progressBarCount = 0;

            for (int i = 0; i < Setting.Elements.Count; i++)
            {
                var    element   = Setting.Elements[i];
                string directory = element.ScanerDirectory;
                string className = element.ScanerName;

                IAssetScaner      scaner  = CreateScanerInstance(className);
                List <ScanReport> reports = scaner.Scan(directory);
                result.Add(directory, reports);

                EditorTools.DisplayProgressBar("资源扫描", ++progressBarCount, Setting.Elements.Count);
            }
            EditorTools.ClearProgressBar();
            return(result);
        }
        /// <summary>
        /// 加密文件
        /// </summary>
        private List <string> EncryptFiles(IAssetEncrypter encrypter, AssetBundleManifest unityManifest, AssetBundleBuilder.BuildParametersContext buildParameters)
        {
            // 加密资源列表
            List <string> encryptList = new List <string>();

            // 如果没有设置加密类
            if (encrypter == null)
            {
                return(encryptList);
            }

            BuildLogger.Log($"开始加密资源文件");
            string[] allAssetBundles = unityManifest.GetAllAssetBundles();
            int      progressValue   = 0;

            foreach (string bundleName in allAssetBundles)
            {
                string filePath = $"{buildParameters.PipelineOutputDirectory}/{bundleName}";
                if (encrypter.Check(filePath))
                {
                    encryptList.Add(bundleName);

                    // 注意:通过判断文件合法性,规避重复加密一个文件
                    byte[] fileData = File.ReadAllBytes(filePath);
                    if (EditorTools.CheckBundleFileValid(fileData))
                    {
                        byte[] bytes = encrypter.Encrypt(fileData);
                        File.WriteAllBytes(filePath, bytes);
                        BuildLogger.Log($"文件加密完成:{filePath}");
                    }
                }

                // 进度条
                EditorTools.DisplayProgressBar("加密资源包", ++progressValue, allAssetBundles.Length);
            }
            EditorTools.ClearProgressBar();

            return(encryptList);
        }
Example #7
0
        /// <summary>
        /// 清理无用的材质球属性
        /// </summary>
        public static void ClearMaterialUnusedProperty()
        {
            // 获取所有的打包路径
            List <string> collectDirectorys = AssetBundleCollectorSettingData.GetAllCollectDirectory();

            if (collectDirectorys.Count == 0)
            {
                throw new Exception("打包路径列表不能为空");
            }

            // 获取所有资源列表
            int checkCount   = 0;
            int removedCount = 0;

            string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Material, collectDirectorys.ToArray());
            foreach (string assetPath in findAssets)
            {
                Material mat     = AssetDatabase.LoadAssetAtPath <Material>(assetPath);
                bool     removed = EditorTools.ClearMaterialUnusedProperty(mat);
                if (removed)
                {
                    removedCount++;
                    Debug.LogWarning($"材质球已被处理:{assetPath}");
                }
                EditorTools.DisplayProgressBar("清理无用的材质球属性", ++checkCount, findAssets.Length);
            }
            EditorTools.ClearProgressBar();

            if (removedCount == 0)
            {
                Debug.Log($"没有发现冗余的材质球属性");
            }
            else
            {
                AssetDatabase.SaveAssets();
            }
        }
        private static List <Material> GetAllMaterials()
        {
            int           progressValue = 0;
            List <string> allAssets     = new List <string>(1000);

            // 获取所有打包的资源
            List <AssetCollectInfo> allCollectInfos = AssetBundleCollectorSettingData.GetAllCollectAssets();
            List <string>           collectAssets   = allCollectInfos.Select(t => t.AssetPath).ToList();

            foreach (var assetPath in collectAssets)
            {
                string[] depends = AssetDatabase.GetDependencies(assetPath, true);
                foreach (var depend in depends)
                {
                    if (allAssets.Contains(depend) == false)
                    {
                        allAssets.Add(depend);
                    }
                }
                EditorTools.DisplayProgressBar("获取所有打包资源", ++progressValue, collectAssets.Count);
            }
            EditorTools.ClearProgressBar();

            // 搜集所有材质球
            progressValue = 0;
            var shaderDic = new Dictionary <Shader, List <Material> >(100);

            foreach (var assetPath in allAssets)
            {
                System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
                if (assetType == typeof(UnityEngine.Material))
                {
                    var material = AssetDatabase.LoadAssetAtPath <Material>(assetPath);
                    var shader   = material.shader;
                    if (shader == null)
                    {
                        continue;
                    }

                    if (shaderDic.ContainsKey(shader) == false)
                    {
                        shaderDic.Add(shader, new List <Material>());
                    }
                    if (shaderDic[shader].Contains(material) == false)
                    {
                        shaderDic[shader].Add(material);
                    }
                }
                EditorTools.DisplayProgressBar("搜集所有材质球", ++progressValue, allAssets.Count);
            }
            EditorTools.ClearProgressBar();

            // 返回结果
            var materials = new List <Material>(1000);

            foreach (var valuePair in shaderDic)
            {
                materials.AddRange(valuePair.Value);
            }
            return(materials);
        }
        /// <summary>
        /// 获取构建的资源列表
        /// </summary>
        private List <AssetInfo> GetBuildAssets()
        {
            Dictionary <string, AssetInfo> buildAssets = new Dictionary <string, AssetInfo>();
            Dictionary <string, string>    references  = new Dictionary <string, string>();

            // 1. 获取主动收集的资源
            List <AssetCollectInfo> allCollectAssets = AssetBundleCollectorSettingData.GetAllCollectAssets();

            // 2. 对收集的资源进行依赖分析
            int progressValue = 0;

            foreach (AssetCollectInfo collectInfo in allCollectAssets)
            {
                string           mainAssetPath = collectInfo.AssetPath;
                List <AssetInfo> depends       = GetDependencies(mainAssetPath);
                for (int i = 0; i < depends.Count; i++)
                {
                    AssetInfo assetInfo = depends[i];
                    string    assetPath = assetInfo.AssetPath;

                    // 如果已经存在,则增加该资源的依赖计数
                    if (buildAssets.ContainsKey(assetPath))
                    {
                        buildAssets[assetPath].DependCount++;
                    }
                    else
                    {
                        buildAssets.Add(assetPath, assetInfo);
                        references.Add(assetPath, mainAssetPath);
                    }

                    // 添加资源标记
                    buildAssets[assetPath].AddAssetTags(collectInfo.AssetTags);

                    // 注意:检测是否为主动收集资源
                    if (assetPath == mainAssetPath)
                    {
                        buildAssets[assetPath].IsCollectAsset     = true;
                        buildAssets[assetPath].DontWriteAssetPath = collectInfo.DontWriteAssetPath;
                    }
                }
                EditorTools.DisplayProgressBar("依赖文件分析", ++progressValue, allCollectAssets.Count);
            }
            EditorTools.ClearProgressBar();

            // 3. 移除零依赖的资源
            List <AssetInfo> undependentAssets = new List <AssetInfo>();

            foreach (KeyValuePair <string, AssetInfo> pair in buildAssets)
            {
                if (pair.Value.IsCollectAsset)
                {
                    continue;
                }
                if (pair.Value.DependCount == 0)
                {
                    undependentAssets.Add(pair.Value);
                }
            }
            foreach (var assetInfo in undependentAssets)
            {
                buildAssets.Remove(assetInfo.AssetPath);
            }

            // 4. 设置资源标签和变种
            progressValue = 0;
            foreach (KeyValuePair <string, AssetInfo> pair in buildAssets)
            {
                var assetInfo             = pair.Value;
                var bundleLabelAndVariant = AssetBundleCollectorSettingData.GetBundleLabelAndVariant(assetInfo.AssetPath);
                assetInfo.SetBundleLabelAndVariant(bundleLabelAndVariant.BundleLabel, bundleLabelAndVariant.BundleVariant);
                EditorTools.DisplayProgressBar("设置资源标签", ++progressValue, buildAssets.Count);
            }
            EditorTools.ClearProgressBar();

            // 5. 补充零依赖的资源
            foreach (var assetInfo in undependentAssets)
            {
                var referenceAssetPath = references[assetInfo.AssetPath];
                var referenceAssetInfo = buildAssets[referenceAssetPath];
                assetInfo.SetBundleLabelAndVariant(referenceAssetInfo.AssetBundleLabel, referenceAssetInfo.AssetBundleVariant);
                buildAssets.Add(assetInfo.AssetPath, assetInfo);
            }

            // 6. 返回结果
            return(buildAssets.Values.ToList());
        }