/// <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($"没有发现损坏预制件"); } }
private void OnDrawDLC() { // 列表显示 EditorGUILayout.Space(); EditorGUILayout.LabelField($"[ DLC ]"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.DLCFiles.Count; i++) { string filePath = AssetBundleCollectorSettingData.Setting.DLCFiles[i]; EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(filePath); if (GUILayout.Button("-", GUILayout.MaxWidth(40))) { AssetBundleCollectorSettingData.RemoveDLC(filePath); break; } } EditorGUILayout.EndHorizontal(); } // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFilePath("Select File", "Assets/"); if (resultPath != null) { string filePath = EditorTools.AbsolutePathToAssetPath(resultPath); AssetBundleCollectorSettingData.AddDLC(filePath); } } }
public AssetInfo(string assetPath) { AssetPath = assetPath; IsCollectAsset = AssetBundleCollectorSettingData.IsCollectAsset(assetPath); IsSceneAsset = AssetDatabase.GetMainAssetTypeAtPath(assetPath) == typeof(SceneAsset); IsVideoAsset = AssetDatabase.GetMainAssetTypeAtPath(assetPath) == typeof(UnityEngine.Video.VideoClip); }
private void OnDrawShader() { bool isCollectAllShader = AssetBundleCollectorSettingData.Setting.IsCollectAllShaders; string shadersBundleName = AssetBundleCollectorSettingData.Setting.ShadersBundleName; EditorGUILayout.Space(); bool newToggleValue = EditorGUILayout.Toggle("收集所有着色器", isCollectAllShader); if (newToggleValue != isCollectAllShader) { isCollectAllShader = newToggleValue; AssetBundleCollectorSettingData.ModifyShader(isCollectAllShader, shadersBundleName); } if (isCollectAllShader) { string newTextValue = EditorGUILayout.TextField("AssetBundle名称", shadersBundleName, GUILayout.MaxWidth(300)); if (newTextValue != shadersBundleName) { shadersBundleName = newTextValue; AssetBundleCollectorSettingData.ModifyShader(isCollectAllShader, shadersBundleName); } } }
void IBuildTask.Run(BuildContext context) { var buildParameters = context.GetContextObject <AssetBundleBuilder.BuildParametersContext>(); var buildOptions = context.GetContextObject <AssetBundleBuilder.BuildOptionsContext>(); // 检测构建平台是否合法 if (buildParameters.BuildTarget == BuildTarget.NoTarget) { throw new Exception("请选择目标平台"); } // 检测构建版本是否合法 if (EditorTools.IsNumber(buildParameters.BuildVersion.ToString()) == false) { throw new Exception($"版本号格式非法:{buildParameters.BuildVersion}"); } if (buildParameters.BuildVersion < 0) { throw new Exception("请先设置版本号"); } // 检测输出目录是否为空 if (string.IsNullOrEmpty(buildParameters.OutputDirectory)) { throw new Exception("输出目录不能为空"); } // 检测补丁包是否已经存在 string packageDirectory = buildParameters.GetPackageDirectory(); if (Directory.Exists(packageDirectory)) { throw new Exception($"补丁包已经存在:{packageDirectory}"); } // 检测资源收集配置文件 if (AssetBundleCollectorSettingData.GetCollecterCount() == 0) { throw new Exception("配置的资源收集路径为空!"); } // 如果是强制重建 if (buildOptions.IsForceRebuild) { // 删除平台总目录 string platformDirectory = $"{buildParameters.OutputRoot}/{buildParameters.BuildTarget}"; if (EditorTools.DeleteDirectory(platformDirectory)) { BuildLogger.Log($"删除平台总目录:{platformDirectory}"); } } // 如果输出目录不存在 if (EditorTools.CreateDirectory(buildParameters.OutputDirectory)) { BuildLogger.Log($"创建输出目录:{buildParameters.OutputDirectory}"); } }
private void OnDrawCollector() { // 列表显示 EditorGUILayout.Space(); EditorGUILayout.LabelField($"[ Collector ]"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { var collector = AssetBundleCollectorSettingData.Setting.Collectors[i]; string directory = collector.CollectDirectory; string labelClassName = collector.LabelClassName; string filterClassName = collector.FilterClassName; EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(directory); // 标签类 { int index = LabelClassNameToIndex(labelClassName); int newIndex = EditorGUILayout.Popup(index, _labelClassArray, GUILayout.MaxWidth(150)); if (newIndex != index) { labelClassName = IndexToLabelClassName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, labelClassName, filterClassName); } } // 过滤类 { int index = FilterClassNameToIndex(filterClassName); int newIndex = EditorGUILayout.Popup(index, _filterClassArray, GUILayout.MaxWidth(150)); if (newIndex != index) { filterClassName = IndexToFilterClassName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, labelClassName, filterClassName); } } if (GUILayout.Button("-", GUILayout.MaxWidth(40))) { AssetBundleCollectorSettingData.RemoveCollector(directory); break; } } EditorGUILayout.EndHorizontal(); } // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFolderPanel("Select Folder", _lastOpenFolderPath); if (resultPath != null) { _lastOpenFolderPath = EditorTools.AbsolutePathToAssetPath(resultPath); AssetBundleCollectorSettingData.AddCollector(_lastOpenFolderPath); } } }
private void Init() { List <string> packRuleClassNames = AssetBundleCollectorSettingData.GetPackRuleClassNames(); _packRuleClassArray = packRuleClassNames.ToArray(); List <string> filterRuleClassNames = AssetBundleCollectorSettingData.GetFilterRuleClassNames(); _filterRuleClassArray = filterRuleClassNames.ToArray(); }
private void Init() { List <string> labelClassNames = AssetBundleCollectorSettingData.GetLabelClassNames(); _labelClassArray = labelClassNames.ToArray(); List <string> filterClassNames = AssetBundleCollectorSettingData.GetFilterClassNames(); _filterClassArray = filterClassNames.ToArray(); }
/// <summary> /// 执行构建 /// </summary> public void PostAssetBuild() { Debug.Log("------------------------------OnPostAssetBuild------------------------------"); // 检测工作 if (AssetBundleCollectorSettingData.GetCollecterCount() == 0) { throw new Exception("[BuildPatch] 配置的资源收集路径为空!"); } // 准备工作 List <AssetInfo> buildMap = GetBuildMap(); if (buildMap.Count == 0) { throw new Exception("[BuildPatch] 构建列表不能为空"); } Log($"构建列表里总共有{buildMap.Count}个资源需要构建"); List <AssetBundleBuild> buildInfoList = new List <AssetBundleBuild>(buildMap.Count); for (int i = 0; i < buildMap.Count; i++) { AssetInfo assetInfo = buildMap[i]; AssetBundleBuild buildInfo = new AssetBundleBuild(); buildInfo.assetBundleName = assetInfo.AssetBundleLabel; buildInfo.assetBundleVariant = assetInfo.AssetBundleVariant; buildInfo.assetNames = new string[] { assetInfo.AssetPath }; buildInfoList.Add(buildInfo); } // 开始构建 Log($"开始构建......"); BuildAssetBundleOptions opt = MakeBuildOptions(); AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(OutputDirectory, buildInfoList.ToArray(), opt, BuildTarget); if (unityManifest == null) { throw new Exception("[BuildPatch] 构建过程中发生错误!"); } // 加密资源文件 List <string> encryptList = EncryptFiles(unityManifest); // 1. 检测循环依赖 CheckCycleDepend(unityManifest); // 2. 创建补丁文件 CreatePatchManifestFile(unityManifest, buildMap, encryptList); // 3. 创建说明文件 CreateReadmeFile(unityManifest); // 4. 复制更新文件 CopyUpdateFiles(); Log("构建完成!"); }
/// <summary> /// 加载所有DLC文件 /// </summary> public void LoadAllDCL() { string[] files = AssetBundleCollectorSettingData.GetDLCFiles(); for (int i = 0; i < files.Length; i++) { DLContent dlc = DLContent.Deserialize(files[i]); if (dlc != null) { _contents.Add(dlc); } } }
private void OnDrawElement() { // 列表显示 EditorGUILayout.Space(); EditorGUILayout.LabelField($"Collector"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { string directory = AssetBundleCollectorSettingData.Setting.Collectors[i].CollectDirectory; AssetBundleCollectorSetting.ECollectRule packRule = AssetBundleCollectorSettingData.Setting.Collectors[i].CollectRule; string collectorName = AssetBundleCollectorSettingData.Setting.Collectors[i].CollectorName; EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(directory); AssetBundleCollectorSetting.ECollectRule newPackRule = (AssetBundleCollectorSetting.ECollectRule)EditorGUILayout.EnumPopup(packRule, GUILayout.MaxWidth(150)); if (newPackRule != packRule) { packRule = newPackRule; AssetBundleCollectorSettingData.ModifyCollector(directory, packRule, collectorName); } int index = NameToIndex(collectorName); int newIndex = EditorGUILayout.Popup(index, _collectorClassArray, GUILayout.MaxWidth(150)); if (newIndex != index) { string newCollectorName = IndexToName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, packRule, newCollectorName); } if (GUILayout.Button("-", GUILayout.MaxWidth(40))) { AssetBundleCollectorSettingData.RemoveCollector(directory); break; } } EditorGUILayout.EndHorizontal(); } // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFolderPanel("Select Folder", _lastOpenFolderPath); if (resultPath != null) { _lastOpenFolderPath = EditorTools.AbsolutePathToAssetPath(resultPath); AssetBundleCollectorSettingData.AddCollector(_lastOpenFolderPath); } } }
private void OnGUI() { // 列表显示 EditorGUILayout.Space(); EditorGUILayout.LabelField($"Collection List"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Elements.Count; i++) { string folderPath = AssetBundleCollectorSettingData.Setting.Elements[i].FolderPath; AssetBundleCollectorSetting.EFolderPackRule packRule = AssetBundleCollectorSettingData.Setting.Elements[i].PackRule; AssetBundleCollectorSetting.EBundleLabelRule labelRule = AssetBundleCollectorSettingData.Setting.Elements[i].LabelRule; EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(folderPath); AssetBundleCollectorSetting.EFolderPackRule newPackRule = (AssetBundleCollectorSetting.EFolderPackRule)EditorGUILayout.EnumPopup(packRule, GUILayout.MaxWidth(150)); if (newPackRule != packRule) { packRule = newPackRule; AssetBundleCollectorSettingData.ModifyElement(folderPath, packRule, labelRule); } AssetBundleCollectorSetting.EBundleLabelRule newLabelRule = (AssetBundleCollectorSetting.EBundleLabelRule)EditorGUILayout.EnumPopup(labelRule, GUILayout.MaxWidth(150)); if (newLabelRule != labelRule) { labelRule = newLabelRule; AssetBundleCollectorSettingData.ModifyElement(folderPath, packRule, labelRule); } if (GUILayout.Button("-", GUILayout.MaxWidth(40))) { AssetBundleCollectorSettingData.RemoveElement(folderPath); break; } } EditorGUILayout.EndHorizontal(); } // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFolderPanel("+", _lastOpenFolderPath); if (resultPath != null) { _lastOpenFolderPath = EditorTools.AbsolutePathToAssetPath(resultPath); AssetBundleCollectorSettingData.AddElement(_lastOpenFolderPath); } } }
/// <summary> /// 获取指定资源依赖的资源列表 /// 注意:返回列表里已经包括主资源自己 /// </summary> private List <AssetInfo> GetDependencies(string assetPath) { List <AssetInfo> depends = new List <AssetInfo>(); string[] dependArray = AssetDatabase.GetDependencies(assetPath, true); foreach (string dependPath in dependArray) { if (AssetBundleCollectorSettingData.ValidateAsset(dependPath)) { AssetInfo assetInfo = new AssetInfo(dependPath); depends.Add(assetInfo); } } return(depends); }
/// <summary> /// 获取指定资源依赖的资源列表 /// 注意:返回列表里已经包括主资源自己 /// </summary> private List <AssetInfo> GetDependencies(string mainAssetPath) { List <AssetInfo> result = new List <AssetInfo>(); string[] depends = AssetDatabase.GetDependencies(mainAssetPath, true); foreach (string assetPath in depends) { if (AssetBundleCollectorSettingData.IsValidateAsset(assetPath)) { AssetInfo assetInfo = new AssetInfo(assetPath); result.Add(assetInfo); } } return(result); }
/// <summary> /// 清理无用的材质球属性 /// </summary> private void ClearMaterialUnusedProperty() { // 获取所有的打包路径 List <string> collectDirectorys = AssetBundleCollectorSettingData.GetAllCollectDirectory(); if (collectDirectorys.Count == 0) { throw new Exception("[BuildPackage] 打包路径列表不能为空"); } // 获取所有资源列表 int checkCount = 0; int removedCount = 0; string[] guids = AssetDatabase.FindAssets(string.Empty, collectDirectorys.ToArray()); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); string ext = System.IO.Path.GetExtension(assetPath); if (ext == $".{EAssetFileExtension.mat}") { Material mat = AssetDatabase.LoadAssetAtPath <Material>(assetPath); bool removed = EditorTools.ClearMaterialUnusedProperty(mat); if (removed) { removedCount++; Debug.LogWarning($"[Build] 材质球已被处理:{assetPath}"); } } // 进度条相关 checkCount++; EditorUtility.DisplayProgressBar("进度", $"清理无用的材质球属性:{checkCount}/{guids.Length}", (float)checkCount / guids.Length); } EditorUtility.ClearProgressBar(); if (removedCount == 0) { Debug.Log($"没有发现冗余的材质球属性"); } else { AssetDatabase.SaveAssets(); } }
/// <summary> /// 设置资源的标签和变种 /// </summary> private void SetAssetBundleLabelAndVariant(AssetInfo assetInfo) { // 如果资源所在文件夹的名称包含后缀符号,则为变体资源 string folderName = Path.GetDirectoryName(assetInfo.AssetPath); // "Assets/Texture.HD/background.jpg" --> "Assets/Texture.HD" if (Path.HasExtension(folderName)) { string extension = Path.GetExtension(folderName); string label = AssetBundleCollectorSettingData.GetAssetBundleLabel(assetInfo.AssetPath); assetInfo.AssetBundleLabel = label.Replace(extension, string.Empty); assetInfo.AssetBundleVariant = extension.Substring(1); } else { assetInfo.AssetBundleLabel = AssetBundleCollectorSettingData.GetAssetBundleLabel(assetInfo.AssetPath); assetInfo.AssetBundleVariant = PatchDefine.AssetBundleDefaultVariant; } }
/// <summary> /// 检测预制件是否损坏 /// </summary> private void CheckAllPrefabValid() { // 获取所有的打包路径 List <string> collectDirectorys = AssetBundleCollectorSettingData.GetAllCollectDirectory(); if (collectDirectorys.Count == 0) { throw new Exception("[BuildPackage] 打包路径列表不能为空"); } // 获取所有资源列表 int checkCount = 0; int invalidCount = 0; string[] guids = AssetDatabase.FindAssets(string.Empty, collectDirectorys.ToArray()); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); string ext = System.IO.Path.GetExtension(assetPath); if (ext == $".{EAssetFileExtension.prefab}") { UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object)); if (prefab == null) { invalidCount++; Debug.LogError($"[Build] 发现损坏预制件:{assetPath}"); } } // 进度条相关 checkCount++; EditorUtility.DisplayProgressBar("进度", $"检测预制件文件是否损坏:{checkCount}/{guids.Length}", (float)checkCount / guids.Length); } EditorUtility.ClearProgressBar(); if (invalidCount == 0) { Debug.Log($"没有发现损坏预制件"); } }
/// <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(); } }
public static void ImportXmlConfig(string filePath) { if (File.Exists(filePath) == false) { throw new FileNotFoundException(filePath); } if (Path.GetExtension(filePath) != ".xml") { throw new Exception($"Only support xml : {filePath}"); } List <CollectWrapper> wrappers = new List <CollectWrapper>(); // 加载文件 XmlDocument xml = new XmlDocument(); xml.Load(filePath); // 解析文件 XmlElement root = xml.DocumentElement; XmlNodeList nodeList = root.GetElementsByTagName(XmlCollector); if (nodeList.Count == 0) { throw new Exception($"Not found any {XmlCollector}"); } foreach (XmlNode node in nodeList) { XmlElement collect = node as XmlElement; string directory = collect.GetAttribute(XmlDirectory); string packRuleName = collect.GetAttribute(XmlPackRule); string filterRuleName = collect.GetAttribute(XmlFilterRule); string dontWriteAssetPath = collect.GetAttribute(XmlDontWriteAssetPath); string assetTags = collect.GetAttribute(XmlAssetTags); if (Directory.Exists(directory) == false) { throw new Exception($"Not found directory : {directory}"); } if (collect.HasAttribute(XmlPackRule) == false) { throw new Exception($"Not found attribute {XmlPackRule} in collector : {directory}"); } if (collect.HasAttribute(XmlFilterRule) == false) { throw new Exception($"Not found attribute {XmlFilterRule} in collector : {directory}"); } if (collect.HasAttribute(XmlDontWriteAssetPath) == false) { throw new Exception($"Not found attribute {XmlDontWriteAssetPath} in collector : {directory}"); } if (collect.HasAttribute(XmlAssetTags) == false) { throw new Exception($"Not found attribute {XmlAssetTags} in collector : {directory}"); } if (AssetBundleCollectorSettingData.HasPackRuleName(packRuleName) == false) { throw new Exception($"Invalid {nameof(IPackRule)} class type : {packRuleName}"); } if (AssetBundleCollectorSettingData.HasFilterRuleName(filterRuleName) == false) { throw new Exception($"Invalid {nameof(IFilterRule)} class type : {filterRuleName}"); } bool dontWriteAssetPathValue = StringConvert.StringToBool(dontWriteAssetPath); CollectWrapper collectWrapper = new CollectWrapper(directory, packRuleName, filterRuleName, dontWriteAssetPathValue, assetTags); wrappers.Add(collectWrapper); } // 导入配置数据 AssetBundleCollectorSettingData.ClearAllCollector(); foreach (var wrapper in wrappers) { AssetBundleCollectorSettingData.AddCollector(wrapper.CollectDirectory, wrapper.PackRuleName, wrapper.FilterRuleName, wrapper.DontWriteAssetPath, wrapper.AssetTags, false); } // 保存配置数据 AssetBundleCollectorSettingData.SaveFile(); Debug.Log($"导入配置完毕,一共导入{wrappers.Count}个收集器。"); }
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() { int progressBarCount = 0; Dictionary <string, AssetInfo> buildAssets = new Dictionary <string, AssetInfo>(); // 1. 获取主动收集的资源 List <string> allCollectAssets = AssetBundleCollectorSettingData.GetAllCollectAssets(); // 2. 对收集的资源进行依赖分析 foreach (string collectAssetPath in allCollectAssets) { List <AssetInfo> depends = GetDependencies(collectAssetPath); for (int i = 0; i < depends.Count; i++) { AssetInfo assetInfo = depends[i]; if (buildAssets.ContainsKey(assetInfo.AssetPath)) { buildAssets[assetInfo.AssetPath].DependCount++; } else { buildAssets.Add(assetInfo.AssetPath, assetInfo); } // 注意:检测是否为主动收集资源 if (assetInfo.AssetPath == collectAssetPath) { buildAssets[collectAssetPath].IsCollectAsset = true; } } progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"依赖文件分析:{progressBarCount}/{allCollectAssets.Count}", (float)progressBarCount / allCollectAssets.Count); } progressBarCount = 0; EditorUtility.ClearProgressBar(); // 3. 移除零依赖的资源 List <string> removeList = new List <string>(); foreach (KeyValuePair <string, AssetInfo> pair in buildAssets) { if (pair.Value.IsCollectAsset) { continue; } if (pair.Value.DependCount == 0) { removeList.Add(pair.Value.AssetPath); } } for (int i = 0; i < removeList.Count; i++) { buildAssets.Remove(removeList[i]); } // 4. 设置资源标签和变种 foreach (KeyValuePair <string, AssetInfo> pair in buildAssets) { var assetInfo = pair.Value; var bundleLabelAndVariant = AssetBundleCollectorSettingData.GetBundleLabelAndVariant(assetInfo.AssetPath, assetInfo.AssetType); assetInfo.SetBundleLabelAndVariant(bundleLabelAndVariant.BundleLabel, bundleLabelAndVariant.BundleVariant); progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"设置资源标签:{progressBarCount}/{buildAssets.Count}", (float)progressBarCount / buildAssets.Count); } EditorUtility.ClearProgressBar(); // 5. 返回结果 return(buildAssets.Values.ToList()); }
/// <summary> /// 准备工作 /// </summary> private List <AssetInfo> GetBuildMap() { int progressBarCount = 0; Dictionary <string, AssetInfo> allAsset = new Dictionary <string, AssetInfo>(); // 获取所有的收集路径 List <string> collectDirectorys = AssetBundleCollectorSettingData.GetAllCollectDirectory(); if (collectDirectorys.Count == 0) { throw new Exception("[BuildPatch] 配置的资源收集路径为空"); } // 获取所有资源 string[] guids = AssetDatabase.FindAssets(string.Empty, collectDirectorys.ToArray()); foreach (string guid in guids) { string mainAssetPath = AssetDatabase.GUIDToAssetPath(guid); if (AssetBundleCollectorSettingData.IsIgnoreAsset(mainAssetPath)) { continue; } if (ValidateAsset(mainAssetPath) == false) { continue; } List <AssetInfo> depends = GetDependencies(mainAssetPath); for (int i = 0; i < depends.Count; i++) { AssetInfo assetInfo = depends[i]; if (allAsset.ContainsKey(assetInfo.AssetPath)) { allAsset[assetInfo.AssetPath].DependCount++; } else { allAsset.Add(assetInfo.AssetPath, assetInfo); } } // 进度条 progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"依赖文件分析:{progressBarCount}/{guids.Length}", (float)progressBarCount / guids.Length); } EditorUtility.ClearProgressBar(); progressBarCount = 0; // 移除零依赖的资源 List <string> removeList = new List <string>(); foreach (KeyValuePair <string, AssetInfo> pair in allAsset) { if (pair.Value.IsCollectAsset) { continue; } if (pair.Value.DependCount == 0) { removeList.Add(pair.Value.AssetPath); } } for (int i = 0; i < removeList.Count; i++) { allAsset.Remove(removeList[i]); } // 设置资源标签 foreach (KeyValuePair <string, AssetInfo> pair in allAsset) { SetAssetBundleLabelAndVariant(pair.Value); // 进度条 progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"设置资源标签:{progressBarCount}/{allAsset.Count}", (float)progressBarCount / allAsset.Count); } EditorUtility.ClearProgressBar(); // 返回结果 return(allAsset.Values.ToList()); }
/// <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()); }
void IBuildTask.Run(BuildContext context) { var buildParameters = context.GetContextObject <AssetBundleBuilder.BuildParametersContext>(); // 检测构建平台是否合法 if (buildParameters.Parameters.BuildTarget == BuildTarget.NoTarget) { throw new Exception("请选择目标平台"); } // 检测构建版本是否合法 if (buildParameters.Parameters.BuildVersion <= 0) { throw new Exception("请先设置版本号"); } // 检测输出目录是否为空 if (string.IsNullOrEmpty(buildParameters.PipelineOutputDirectory)) { throw new Exception("输出目录不能为空"); } // 检测资源收集配置文件 if (AssetBundleCollectorSettingData.GetCollecterCount() == 0) { throw new Exception("配置的资源收集路径为空"); } // 增量更新时候的必要检测 if (buildParameters.Parameters.IsForceRebuild == false) { // 检测历史版本是否存在 if (AssetBundleBuilderHelper.HasAnyPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot) == false) { throw new Exception("没有发现任何历史版本,请尝试强制重建"); } // 检测构建版本是否合法 int maxPackageVersion = AssetBundleBuilderHelper.GetMaxPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot); if (buildParameters.Parameters.BuildVersion <= maxPackageVersion) { throw new Exception("构建版本不能小于历史版本"); } // 检测补丁包是否已经存在 string packageDirectory = buildParameters.GetPackageDirectory(); if (Directory.Exists(packageDirectory)) { throw new Exception($"补丁包已经存在:{packageDirectory}"); } // 检测内置资源标记是否一致 PatchManifest oldPatchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory); if (buildParameters.Parameters.BuildinTags != oldPatchManifest.BuildinTags) { throw new Exception($"增量更新时内置资源标记必须一致:{buildParameters.Parameters.BuildinTags} != {oldPatchManifest.BuildinTags}"); } } // 如果是强制重建 if (buildParameters.Parameters.IsForceRebuild) { // 删除平台总目录 string platformDirectory = $"{buildParameters.Parameters.OutputRoot}/{buildParameters.Parameters.BuildTarget}"; if (EditorTools.DeleteDirectory(platformDirectory)) { BuildLogger.Log($"删除平台总目录:{platformDirectory}"); } } // 如果输出目录不存在 if (EditorTools.CreateDirectory(buildParameters.PipelineOutputDirectory)) { BuildLogger.Log($"创建输出目录:{buildParameters.PipelineOutputDirectory}"); } }
private void Init() { List <string> names = AssetBundleCollectorSettingData.GetCollectorNames(); _collectorClassArray = names.ToArray(); }
/// <summary> /// 准备工作 /// </summary> private List <AssetInfo> GetBuildMap() { int progressBarCount = 0; Dictionary <string, AssetInfo> buildMap = new Dictionary <string, AssetInfo>(); // 获取要收集的资源 List <string> allCollectAssets = AssetBundleCollectorSettingData.GetAllCollectAssets(); // 进行依赖分析 foreach (string mainAssetPath in allCollectAssets) { List <AssetInfo> depends = GetDependencies(mainAssetPath); for (int i = 0; i < depends.Count; i++) { AssetInfo assetInfo = depends[i]; if (buildMap.ContainsKey(assetInfo.AssetPath)) { buildMap[assetInfo.AssetPath].DependCount++; } else { buildMap.Add(assetInfo.AssetPath, assetInfo); } } progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"依赖文件分析:{progressBarCount}/{allCollectAssets.Count}", (float)progressBarCount / allCollectAssets.Count); } EditorUtility.ClearProgressBar(); progressBarCount = 0; // 移除零依赖的资源 List <string> removeList = new List <string>(); foreach (KeyValuePair <string, AssetInfo> pair in buildMap) { if (pair.Value.IsCollectAsset) { continue; } if (pair.Value.DependCount == 0) { removeList.Add(pair.Value.AssetPath); } } for (int i = 0; i < removeList.Count; i++) { buildMap.Remove(removeList[i]); } // 设置资源标签 foreach (KeyValuePair <string, AssetInfo> pair in buildMap) { var assetInfo = pair.Value; var labelAndVariant = AssetBundleCollectorSettingData.GetBundleLabelAndVariant(assetInfo.AssetPath); assetInfo.AssetBundleLabel = labelAndVariant.BundleLabel; assetInfo.AssetBundleVariant = labelAndVariant.BundleVariant; progressBarCount++; EditorUtility.DisplayProgressBar("进度", $"设置资源标签:{progressBarCount}/{buildMap.Count}", (float)progressBarCount / buildMap.Count); } EditorUtility.ClearProgressBar(); // 返回结果 return(buildMap.Values.ToList()); }
private void OnDrawCollector() { // 着色器选项 EditorGUILayout.Space(); bool isCollectAllShader = EditorGUILayout.Toggle("收集所有着色器", AssetBundleCollectorSettingData.Setting.IsCollectAllShaders); if (isCollectAllShader != AssetBundleCollectorSettingData.Setting.IsCollectAllShaders) { AssetBundleCollectorSettingData.ModifyShader(isCollectAllShader, AssetBundleCollectorSettingData.Setting.ShadersBundleName); } if (isCollectAllShader) { string shadersBundleName = EditorGUILayout.TextField("AssetBundle名称", AssetBundleCollectorSettingData.Setting.ShadersBundleName); if (shadersBundleName != AssetBundleCollectorSettingData.Setting.ShadersBundleName) { AssetBundleCollectorSettingData.ModifyShader(isCollectAllShader, shadersBundleName); } } // 列表显示 EditorGUILayout.Space(); EditorGUILayout.LabelField($"[ Collector ]"); _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { var collector = AssetBundleCollectorSettingData.Setting.Collectors[i]; string directory = collector.CollectDirectory; string packRuleClassName = collector.PackRuleClassName; string filterRuleClassName = collector.FilterRuleClassName; EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(directory); // IPackRule { int index = PackRuleClassNameToIndex(packRuleClassName); int newIndex = EditorGUILayout.Popup(index, _packRuleClassArray, GUILayout.MaxWidth(200)); if (newIndex != index) { packRuleClassName = IndexToPackRuleClassName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleClassName, filterRuleClassName); } } // IFilterRule { int index = FilterRuleClassNameToIndex(filterRuleClassName); int newIndex = EditorGUILayout.Popup(index, _filterRuleClassArray, GUILayout.MaxWidth(150)); if (newIndex != index) { filterRuleClassName = IndexToFilterRuleClassName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleClassName, filterRuleClassName); } } if (GUILayout.Button("-", GUILayout.MaxWidth(40))) { AssetBundleCollectorSettingData.RemoveCollector(directory); break; } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFolderPanel("Select Folder", _lastOpenFolderPath); if (resultPath != null) { _lastOpenFolderPath = EditorTools.AbsolutePathToAssetPath(resultPath); string defaultPackRuleClassName = nameof(PackExplicit); string defaultFilterRuleClassName = nameof(CollectAll); AssetBundleCollectorSettingData.AddCollector(_lastOpenFolderPath, defaultPackRuleClassName, defaultFilterRuleClassName); } } // 导入配置按钮 if (GUILayout.Button("Import Config")) { string resultPath = EditorTools.OpenFilePath("Select Folder", _lastOpenFolderPath); if (resultPath != null) { CollectorConfigImporter.ImportXmlConfig(resultPath); } } }
private void OnDrawCollector() { // 列表显示 EditorGUILayout.Space(); _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { var collector = AssetBundleCollectorSettingData.Setting.Collectors[i]; string directory = collector.CollectDirectory; string packRuleName = collector.PackRuleName; string filterRuleName = collector.FilterRuleName; bool dontWriteAssetPath = collector.DontWriteAssetPath; string assetTags = collector.AssetTags; EditorGUILayout.BeginHorizontal(); { // Directory EditorGUILayout.LabelField(directory, GUILayout.MinWidth(GuiDirecotryMinSize), GUILayout.MaxWidth(GuiDirecotryMaxSize)); // IPackRule { int index = PackRuleNameToIndex(packRuleName); int newIndex = EditorGUILayout.Popup(index, _packRuleArray, GUILayout.MinWidth(GuiPackRuleSize), GUILayout.MaxWidth(GuiPackRuleSize)); if (newIndex != index) { packRuleName = IndexToPackRuleName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleName, filterRuleName, dontWriteAssetPath, assetTags); } } // IFilterRule { int index = FilterRuleNameToIndex(filterRuleName); int newIndex = EditorGUILayout.Popup(index, _filterRuleArray, GUILayout.MinWidth(GuiFilterRuleSize), GUILayout.MaxWidth(GuiFilterRuleSize)); if (newIndex != index) { filterRuleName = IndexToFilterRuleName(newIndex); AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleName, filterRuleName, dontWriteAssetPath, assetTags); } } // DontWriteAssetPath { bool newToggleValue = EditorGUILayout.Toggle(dontWriteAssetPath, GUILayout.MinWidth(GuiDontWriteAssetPathSize), GUILayout.MaxWidth(GuiDontWriteAssetPathSize)); if (newToggleValue != dontWriteAssetPath) { dontWriteAssetPath = newToggleValue; AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleName, filterRuleName, dontWriteAssetPath, assetTags); } } // AssetTags { string newTextValue = EditorGUILayout.TextField(assetTags, GUILayout.MinWidth(GuiAssetTagsMinSize), GUILayout.MaxWidth(GuiAssetTagsMaxSize)); if (newTextValue != assetTags) { assetTags = newTextValue; AssetBundleCollectorSettingData.ModifyCollector(directory, packRuleName, filterRuleName, dontWriteAssetPath, assetTags); } } if (GUILayout.Button("-", GUILayout.MinWidth(GuiBtnSize), GUILayout.MaxWidth(GuiBtnSize))) { AssetBundleCollectorSettingData.RemoveCollector(directory); break; } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); // 添加按钮 if (GUILayout.Button("+")) { string resultPath = EditorTools.OpenFolderPanel("Select Folder", _lastOpenFolderPath); if (resultPath != null) { _lastOpenFolderPath = EditorTools.AbsolutePathToAssetPath(resultPath); string defaultPackRuleName = nameof(PackExplicit); string defaultFilterRuleName = nameof(CollectAll); bool defaultDontWriteAssetPathValue = false; string defaultAssetTag = string.Empty; AssetBundleCollectorSettingData.AddCollector(_lastOpenFolderPath, defaultPackRuleName, defaultFilterRuleName, defaultDontWriteAssetPathValue, defaultAssetTag); } } // 导入配置按钮 if (GUILayout.Button("Import Config")) { string resultPath = EditorTools.OpenFilePath("Select File", "Assets/", "xml"); if (resultPath != null) { CollectorConfigImporter.ImportXmlConfig(resultPath); } } }