/// <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); }
/// <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()); }