commit 4a023c107cbac80d75c67b24f8acc75dd0cbd9b2
Author: liutao <821580467@qq.com>
Date: Wed Jan 21 15:46:51 2026 +0800
init version
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..c6cd07e
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,83 @@
+# CHANGELOG
+
+All notable changes to this package will be documented in this file.
+
+## [2.1.1] - 2024-01-17
+
+### Fixed
+
+- (#224) 修复了编辑器模式打包时 SimulateBuild 报错的问题。
+- (#223) 修复了资源构建界面读取配置导致的报错问题。
+
+### Added
+
+- 支持共享资源打包规则,可以定制化独立的构建规则。
+
+ ```c#
+ public class BuildParameters
+ {
+ ///
+ /// 是否启用共享资源打包
+ ///
+ public bool EnableSharePackRule = false;
+ }
+ ```
+
+- 微信小游戏平台,资源下载器支持底层缓存查询。
+
+## [2.1.0] - 2023-12-27
+
+升级了 Scriptable build pipeline (SBP) 的版本,来解决图集引用的精灵图片冗余问题。
+
+### Fixed
+
+- (#195) 修复了在EditorPlayMode模式下,AssetHandle.GetDownloadStatus()发生异常的问题。
+- (#201) 修复了断点续传失效的问题。
+- (#202) 修复了打包参数FileNameStyle设置为BundleName后,IQueryServices会一直返回true的问题。
+- (#205) 修复了HybridCLR插件里创建资源下载器触发的异常。
+- (#210) 修复了DownloaderOperation在未开始下载前,内部的PackageName为空的问题。
+- (#220) 修复了资源收集界面关闭后,撤回操作还会生效的问题。
+- 修复了下载器合并后重新计算下载字节数不正确的问题。
+
+### Improvements
+
+- (#198) 资源收集界面禁用的分组不再检测合法性。
+- (#203) 资源构建类容许自定义打包的输出目录。
+- 资源构建报告增加未依赖的资源信息列表。
+
+### Changed
+
+- IBuildinQueryServices和IDeliveryQueryServices查询方法变更。
+
+ ```c#
+ public interface IBuildinQueryServices
+ {
+ ///
+ /// 查询是否为应用程序内置的资源文件
+ ///
+ /// 包裹名称
+ /// 文件名称(包含文件的后缀格式)
+ /// 文件哈希值
+ /// 返回查询结果
+ bool Query(string packageName, string fileName, string fileCRC);
+ }
+
+ public interface IDeliveryQueryServices
+ {
+ ///
+ /// 查询是否为开发者分发的资源文件
+ ///
+ /// 包裹名称
+ /// 文件名称(包含文件的后缀格式)
+ /// 文件哈希值
+ /// 返回查询结果
+ bool Query(string packageName, string fileName, string fileCRC);
+ }
+ ```
+
+
+
+### Removed
+
+- (#212) 移除了构建报告里的资源冗余信息列表。
+
diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta
new file mode 100644
index 0000000..838e3ed
--- /dev/null
+++ b/CHANGELOG.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: db680274cf006c548abff57b7e1894b4
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor.meta b/Editor.meta
new file mode 100644
index 0000000..22c2889
--- /dev/null
+++ b/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ac093515ae764b94aa07be91d4ba978b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder.meta b/Editor/AssetBundleBuilder.meta
new file mode 100644
index 0000000..c1b5f4b
--- /dev/null
+++ b/Editor/AssetBundleBuilder.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1fdecc5500229d44887425ce619352fc
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilder.cs b/Editor/AssetBundleBuilder/AssetBundleBuilder.cs
new file mode 100644
index 0000000..102c02a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilder.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Linq;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilder
+ {
+ private readonly BuildContext _buildContext = new BuildContext();
+
+ ///
+ /// 构建资源包
+ ///
+ public BuildResult Run(BuildParameters buildParameters, List buildPipeline, bool enableLog)
+ {
+ // 检测构建参数是否为空
+ if (buildParameters == null)
+ throw new Exception($"{nameof(buildParameters)} is null !");
+
+ // 检测构建参数是否为空
+ if (buildPipeline.Count == 0)
+ throw new Exception($"Build pipeline is empty !");
+
+ // 清空旧数据
+ _buildContext.ClearAllContext();
+
+ // 构建参数
+ var buildParametersContext = new BuildParametersContext(buildParameters);
+ _buildContext.SetContextObject(buildParametersContext);
+
+ // 初始化日志
+ BuildLogger.InitLogger(enableLog);
+
+ // 执行构建流程
+ Debug.Log($"Begin to build package : {buildParameters.PackageName} by {buildParameters.BuildPipeline}");
+ var buildResult = BuildRunner.Run(buildPipeline, _buildContext);
+ if (buildResult.Success)
+ {
+ buildResult.OutputPackageDirectory = buildParametersContext.GetPackageOutputDirectory();
+ BuildLogger.Log("Resource pipeline build success");
+ }
+ else
+ {
+ BuildLogger.Error($"{buildParameters.BuildPipeline} build failed !");
+ BuildLogger.Error($"An error occurred in build task {buildResult.FailedTask}");
+ BuildLogger.Error(buildResult.ErrorInfo);
+ }
+
+ return buildResult;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilder.cs.meta b/Editor/AssetBundleBuilder/AssetBundleBuilder.cs.meta
new file mode 100644
index 0000000..8060114
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilder.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: de7563040250b4e4a835d1fc90238e38
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs b/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs
new file mode 100644
index 0000000..45cd531
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs
@@ -0,0 +1,28 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public static class AssetBundleBuilderHelper
+ {
+ ///
+ /// 获取默认的输出根路录
+ ///
+ public static string GetDefaultBuildOutputRoot()
+ {
+ string projectPath = EditorTools.GetProjectPath();
+ return $"{projectPath}/Bundles";
+ }
+
+ ///
+ /// 获取流文件夹路径
+ ///
+ public static string GetStreamingAssetsRoot()
+ {
+ return $"{Application.dataPath}/StreamingAssets/{YooAssetSettingsData.Setting.DefaultYooFolderName}/";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta b/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta
new file mode 100644
index 0000000..2cbe160
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f48abdec05f0dbe438a83e181fe6bc93
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs b/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs
new file mode 100644
index 0000000..78e4abd
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs
@@ -0,0 +1,93 @@
+using System;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public static class AssetBundleBuilderSetting
+ {
+ // EBuildPipeline
+ public static EBuildPipeline GetPackageBuildPipeline(string packageName)
+ {
+ string key = $"{Application.productName}_{packageName}_{nameof(EBuildPipeline)}";
+ return (EBuildPipeline)EditorPrefs.GetInt(key, (int)EBuildPipeline.BuiltinBuildPipeline);
+ }
+ public static void SetPackageBuildPipeline(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{nameof(EBuildPipeline)}";
+ EditorPrefs.SetInt(key, (int)buildPipeline);
+ }
+
+ // EBuildMode
+ public static EBuildMode GetPackageBuildMode(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildMode)}";
+ return (EBuildMode)EditorPrefs.GetInt(key, (int)EBuildMode.ForceRebuild);
+ }
+ public static void SetPackageBuildMode(string packageName, EBuildPipeline buildPipeline, EBuildMode buildMode)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildMode)}";
+ EditorPrefs.SetInt(key, (int)buildMode);
+ }
+
+ // ECompressOption
+ public static ECompressOption GetPackageCompressOption(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
+ return (ECompressOption)EditorPrefs.GetInt(key, (int)ECompressOption.LZ4);
+ }
+ public static void SetPackageCompressOption(string packageName, EBuildPipeline buildPipeline, ECompressOption compressOption)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
+ EditorPrefs.SetInt(key, (int)compressOption);
+ }
+
+ // EFileNameStyle
+ public static EFileNameStyle GetPackageFileNameStyle(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
+ return (EFileNameStyle)EditorPrefs.GetInt(key, (int)EFileNameStyle.HashName);
+ }
+ public static void SetPackageFileNameStyle(string packageName, EBuildPipeline buildPipeline, EFileNameStyle fileNameStyle)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
+ EditorPrefs.SetInt(key, (int)fileNameStyle);
+ }
+
+ // EBuildinFileCopyOption
+ public static EBuildinFileCopyOption GetPackageBuildinFileCopyOption(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
+ return (EBuildinFileCopyOption)EditorPrefs.GetInt(key, (int)EBuildinFileCopyOption.None);
+ }
+ public static void SetPackageBuildinFileCopyOption(string packageName, EBuildPipeline buildPipeline, EBuildinFileCopyOption buildinFileCopyOption)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
+ EditorPrefs.SetInt(key, (int)buildinFileCopyOption);
+ }
+
+ // BuildFileCopyParams
+ public static string GetPackageBuildinFileCopyParams(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
+ return EditorPrefs.GetString(key, string.Empty);
+ }
+ public static void SetPackageBuildinFileCopyParams(string packageName, EBuildPipeline buildPipeline, string buildinFileCopyParams)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
+ EditorPrefs.SetString(key, buildinFileCopyParams);
+ }
+
+ // EncyptionClassName
+ public static string GetPackageEncyptionClassName(string packageName, EBuildPipeline buildPipeline)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionClassName";
+ return EditorPrefs.GetString(key, string.Empty);
+ }
+ public static void SetPackageEncyptionClassName(string packageName, EBuildPipeline buildPipeline, string encyptionClassName)
+ {
+ string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionClassName";
+ EditorPrefs.SetString(key, encyptionClassName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta b/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta
new file mode 100644
index 0000000..a8a559c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 09788b4733bab2d4792fdd5d28e7653c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs
new file mode 100644
index 0000000..d6ea3ea
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs
@@ -0,0 +1,161 @@
+#if UNITY_2019_4_OR_NEWER
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using UnityEditor.UIElements;
+using UnityEngine.UIElements;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilderWindow : EditorWindow
+ {
+ [MenuItem("YooAsset/AssetBundle Builder", false, 102)]
+ public static void OpenWindow()
+ {
+ AssetBundleBuilderWindow window = GetWindow("AssetBundle Builder", true, WindowsDefine.DockedWindowTypes);
+ window.minSize = new Vector2(800, 600);
+ }
+
+ private string _buildPackage;
+ private EBuildPipeline _buildPipeline;
+
+ private Toolbar _toolbar;
+ private ToolbarMenu _packageMenu;
+ private ToolbarMenu _pipelineMenu;
+ private VisualElement _container;
+
+
+ public void CreateGUI()
+ {
+ try
+ {
+ VisualElement root = this.rootVisualElement;
+
+ // 加载布局文件
+ var visualAsset = UxmlLoader.LoadWindowUXML();
+ if (visualAsset == null)
+ return;
+
+ visualAsset.CloneTree(root);
+ _toolbar = root.Q("Toolbar");
+ _container = root.Q("Container");
+
+ // 检测构建包裹
+ var packageNames = GetBuildPackageNames();
+ if (packageNames.Count == 0)
+ {
+ var label = new Label();
+ label.text = "Not found any package";
+ label.style.width = 100;
+ _toolbar.Add(label);
+ return;
+ }
+
+ // 构建包裹
+ {
+ _buildPackage = packageNames[0];
+ _packageMenu = new ToolbarMenu();
+ _packageMenu.style.width = 200;
+ foreach (var packageName in packageNames)
+ {
+ _packageMenu.menu.AppendAction(packageName, PackageMenuAction, PackageMenuFun, packageName);
+ }
+ _toolbar.Add(_packageMenu);
+ }
+
+ // 构建管线
+ {
+ _pipelineMenu = new ToolbarMenu();
+ _pipelineMenu.style.width = 200;
+ _pipelineMenu.menu.AppendAction(EBuildPipeline.BuiltinBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.BuiltinBuildPipeline);
+ _pipelineMenu.menu.AppendAction(EBuildPipeline.ScriptableBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.ScriptableBuildPipeline);
+ _pipelineMenu.menu.AppendAction(EBuildPipeline.RawFileBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.RawFileBuildPipeline);
+ _toolbar.Add(_pipelineMenu);
+ }
+
+ RefreshBuildPipelineView();
+ }
+ catch (Exception e)
+ {
+ Debug.LogError(e.ToString());
+ }
+ }
+
+ private void RefreshBuildPipelineView()
+ {
+ // 清空扩展区域
+ _container.Clear();
+
+ _buildPipeline = AssetBundleBuilderSetting.GetPackageBuildPipeline(_buildPackage);
+ _packageMenu.text = _buildPackage;
+ _pipelineMenu.text = _buildPipeline.ToString();
+
+ var buildTarget = EditorUserBuildSettings.activeBuildTarget;
+ if (_buildPipeline == EBuildPipeline.BuiltinBuildPipeline)
+ {
+ var viewer = new BuiltinBuildPipelineViewer(_buildPackage, buildTarget, _container);
+ }
+ else if (_buildPipeline == EBuildPipeline.ScriptableBuildPipeline)
+ {
+ var viewer = new ScriptableBuildPipelineViewer(_buildPackage, buildTarget, _container);
+ }
+ else if (_buildPipeline == EBuildPipeline.RawFileBuildPipeline)
+ {
+ var viewer = new RawfileBuildpipelineViewer(_buildPackage, buildTarget, _container);
+ }
+ else
+ {
+ throw new System.NotImplementedException(_buildPipeline.ToString());
+ }
+ }
+ private List GetBuildPackageNames()
+ {
+ List result = new List();
+ foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
+ {
+ result.Add(package.PackageName);
+ }
+ return result;
+ }
+
+ private void PackageMenuAction(DropdownMenuAction action)
+ {
+ var packageName = (string)action.userData;
+ if (_buildPackage != packageName)
+ {
+ _buildPackage = packageName;
+ RefreshBuildPipelineView();
+ }
+ }
+ private DropdownMenuAction.Status PackageMenuFun(DropdownMenuAction action)
+ {
+ var packageName = (string)action.userData;
+ if (_buildPackage == packageName)
+ return DropdownMenuAction.Status.Checked;
+ else
+ return DropdownMenuAction.Status.Normal;
+ }
+
+ private void PipelineMenuAction(DropdownMenuAction action)
+ {
+ var pipelineType = (EBuildPipeline)action.userData;
+ if (_buildPipeline != pipelineType)
+ {
+ _buildPipeline = pipelineType;
+ AssetBundleBuilderSetting.SetPackageBuildPipeline(_buildPackage, pipelineType);
+ RefreshBuildPipelineView();
+ }
+ }
+ private DropdownMenuAction.Status PipelineMenuFun(DropdownMenuAction action)
+ {
+ var pipelineType = (EBuildPipeline)action.userData;
+ if (_buildPipeline == pipelineType)
+ return DropdownMenuAction.Status.Checked;
+ else
+ return DropdownMenuAction.Status.Normal;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs.meta b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs.meta
new file mode 100644
index 0000000..2e33fe9
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 66e43420e95cd0b4bae8803a31e9817b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml
new file mode 100644
index 0000000..633b4f8
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml.meta b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml.meta
new file mode 100644
index 0000000..1e8aa23
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleBuilderWindow.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 28ba29adb4949284e8c48893218b0d9a
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs b/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs
new file mode 100644
index 0000000..761b212
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs
@@ -0,0 +1,100 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public static class AssetBundleSimulateBuilder
+ {
+ ///
+ /// 模拟构建
+ ///
+ public static string SimulateBuild(string buildPipelineName, string packageName)
+ {
+ if (buildPipelineName == EBuildPipeline.BuiltinBuildPipeline.ToString())
+ {
+ BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
+ buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
+ buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
+ buildParameters.BuildPipeline = buildPipelineName;
+ buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
+ buildParameters.BuildMode = EBuildMode.SimulateBuild;
+ buildParameters.PackageName = packageName;
+ buildParameters.PackageVersion = "Simulate";
+ buildParameters.FileNameStyle = EFileNameStyle.HashName;
+ buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
+ buildParameters.BuildinFileCopyParams = string.Empty;
+
+ BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
+ var buildResult = pipeline.Run(buildParameters, false);
+ if (buildResult.Success)
+ {
+ string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
+ return manifestFilePath;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else if (buildPipelineName == EBuildPipeline.ScriptableBuildPipeline.ToString())
+ {
+ ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
+ buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
+ buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
+ buildParameters.BuildPipeline = buildPipelineName;
+ buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
+ buildParameters.BuildMode = EBuildMode.SimulateBuild;
+ buildParameters.PackageName = packageName;
+ buildParameters.PackageVersion = "Simulate";
+ buildParameters.FileNameStyle = EFileNameStyle.HashName;
+ buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
+ buildParameters.BuildinFileCopyParams = string.Empty;
+
+ ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
+ var buildResult = pipeline.Run(buildParameters, true);
+ if (buildResult.Success)
+ {
+ string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
+ return manifestFilePath;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else if (buildPipelineName == EBuildPipeline.RawFileBuildPipeline.ToString())
+ {
+ RawFileBuildParameters buildParameters = new RawFileBuildParameters();
+ buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
+ buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
+ buildParameters.BuildPipeline = buildPipelineName;
+ buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
+ buildParameters.BuildMode = EBuildMode.SimulateBuild;
+ buildParameters.PackageName = packageName;
+ buildParameters.PackageVersion = "Simulate";
+ buildParameters.FileNameStyle = EFileNameStyle.HashName;
+ buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
+ buildParameters.BuildinFileCopyParams = string.Empty;
+
+ RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
+ var buildResult = pipeline.Run(buildParameters, true);
+ if (buildResult.Success)
+ {
+ string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
+ return manifestFilePath;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new System.NotImplementedException(buildPipelineName);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs.meta b/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs.meta
new file mode 100644
index 0000000..7dc11b8
--- /dev/null
+++ b/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f94918fa1ea63c34fa0e49fdad4119cf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildAssetInfo.cs b/Editor/AssetBundleBuilder/BuildAssetInfo.cs
new file mode 100644
index 0000000..b23c7b5
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildAssetInfo.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace YooAsset.Editor
+{
+ public class BuildAssetInfo
+ {
+ private bool _isAddAssetTags = false;
+ private readonly HashSet _referenceBundleNames = new HashSet();
+
+ ///
+ /// 收集器类型
+ ///
+ public ECollectorType CollectorType { private set; get; }
+
+ ///
+ /// 资源包完整名称
+ ///
+ public string BundleName { private set; get; }
+
+ ///
+ /// 可寻址地址
+ ///
+ public string Address { private set; get; }
+
+ ///
+ /// 资源信息
+ ///
+ public AssetInfo AssetInfo { private set; get; }
+
+ ///
+ /// 资源的分类标签
+ ///
+ public readonly List AssetTags = new List();
+
+ ///
+ /// 依赖的所有资源
+ /// 注意:包括零依赖资源和冗余资源(资源包名无效)
+ ///
+ public List AllDependAssetInfos { private set; get; }
+
+
+ public BuildAssetInfo(ECollectorType collectorType, string bundleName, string address, AssetInfo assetInfo)
+ {
+ CollectorType = collectorType;
+ BundleName = bundleName;
+ Address = address;
+ AssetInfo = assetInfo;
+ }
+ public BuildAssetInfo(AssetInfo assetInfo)
+ {
+ CollectorType = ECollectorType.None;
+ BundleName = string.Empty;
+ Address = string.Empty;
+ AssetInfo = assetInfo;
+ }
+
+
+ ///
+ /// 设置所有依赖的资源
+ ///
+ public void SetDependAssetInfos(List dependAssetInfos)
+ {
+ if (AllDependAssetInfos != null)
+ throw new System.Exception("Should never get here !");
+
+ AllDependAssetInfos = dependAssetInfos;
+ }
+
+ ///
+ /// 设置资源包名称
+ ///
+ public void SetBundleName(string bundleName)
+ {
+ if (HasBundleName())
+ throw new System.Exception("Should never get here !");
+
+ BundleName = bundleName;
+ }
+
+ ///
+ /// 添加资源的分类标签
+ /// 说明:原始定义的资源分类标签
+ ///
+ public void AddAssetTags(List tags)
+ {
+ if (_isAddAssetTags)
+ throw new Exception("Should never get here !");
+ _isAddAssetTags = true;
+
+ foreach (var tag in tags)
+ {
+ if (AssetTags.Contains(tag) == false)
+ {
+ AssetTags.Add(tag);
+ }
+ }
+ }
+
+ ///
+ /// 添加关联的资源包名称
+ ///
+ public void AddReferenceBundleName(string bundleName)
+ {
+ if (string.IsNullOrEmpty(bundleName))
+ throw new Exception("Should never get here !");
+
+ if (_referenceBundleNames.Contains(bundleName) == false)
+ _referenceBundleNames.Add(bundleName);
+ }
+
+ ///
+ /// 资源包名是否存在
+ ///
+ public bool HasBundleName()
+ {
+ if (string.IsNullOrEmpty(BundleName))
+ return false;
+ else
+ return true;
+ }
+
+ ///
+ /// 获取关联资源包的数量
+ ///
+ public int GetReferenceBundleCount()
+ {
+ return _referenceBundleNames.Count;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildAssetInfo.cs.meta b/Editor/AssetBundleBuilder/BuildAssetInfo.cs.meta
new file mode 100644
index 0000000..d7e1149
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildAssetInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 447008dd110b8d746aafbe88c78bee5d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildBundleInfo.cs b/Editor/AssetBundleBuilder/BuildBundleInfo.cs
new file mode 100644
index 0000000..d009ec5
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildBundleInfo.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class BuildBundleInfo
+ {
+ #region 补丁文件的关键信息
+ ///
+ /// Unity引擎生成的哈希值(构建内容的哈希值)
+ ///
+ public string PackageUnityHash { set; get; }
+
+ ///
+ /// Unity引擎生成的CRC
+ ///
+ public uint PackageUnityCRC { set; get; }
+
+ ///
+ /// 文件哈希值
+ ///
+ public string PackageFileHash { set; get; }
+
+ ///
+ /// 文件哈希值
+ ///
+ public string PackageFileCRC { set; get; }
+
+ ///
+ /// 文件哈希值
+ ///
+ public long PackageFileSize { set; get; }
+
+ ///
+ /// 构建输出的文件路径
+ ///
+ public string BuildOutputFilePath { set; get; }
+
+ ///
+ /// 补丁包的源文件路径
+ ///
+ public string PackageSourceFilePath { set; get; }
+
+ ///
+ /// 补丁包的目标文件路径
+ ///
+ public string PackageDestFilePath { set; get; }
+
+ ///
+ /// 加密生成文件的路径
+ /// 注意:如果未加密该路径为空
+ ///
+ public string EncryptedFilePath { set; get; }
+ #endregion
+
+
+ ///
+ /// 参与构建的资源列表
+ /// 注意:不包含零依赖资源和冗余资源
+ ///
+ public readonly List MainAssets = new List();
+
+ ///
+ /// 资源包名称
+ ///
+ public string BundleName { private set; get; }
+
+ ///
+ /// 加密文件
+ ///
+ public bool Encrypted { set; get; }
+
+
+ public BuildBundleInfo(string bundleName)
+ {
+ BundleName = bundleName;
+ }
+
+ ///
+ /// 添加一个打包资源
+ ///
+ public void PackAsset(BuildAssetInfo buildAsset)
+ {
+ if (IsContainsAsset(buildAsset.AssetInfo.AssetPath))
+ throw new System.Exception($"Should never get here ! Asset is existed : {buildAsset.AssetInfo.AssetPath}");
+
+ MainAssets.Add(buildAsset);
+ }
+
+ ///
+ /// 是否包含指定资源
+ ///
+ public bool IsContainsAsset(string assetPath)
+ {
+ foreach (var buildAsset in MainAssets)
+ {
+ if (buildAsset.AssetInfo.AssetPath == assetPath)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// 获取构建的资源路径列表
+ ///
+ public string[] GetAllMainAssetPaths()
+ {
+ return MainAssets.Select(t => t.AssetInfo.AssetPath).ToArray();
+ }
+
+ ///
+ /// 获取该资源包内的所有资源(包括零依赖资源和冗余资源)
+ ///
+ public List GetAllBuiltinAssetPaths()
+ {
+ var packAssets = GetAllMainAssetPaths();
+ List result = new List(packAssets);
+ foreach (var buildAsset in MainAssets)
+ {
+ if (buildAsset.AllDependAssetInfos == null)
+ continue;
+ foreach (var dependAssetInfo in buildAsset.AllDependAssetInfos)
+ {
+ // 注意:依赖资源里只添加零依赖资源和冗余资源
+ if (dependAssetInfo.HasBundleName() == false)
+ {
+ if (result.Contains(dependAssetInfo.AssetInfo.AssetPath) == false)
+ result.Add(dependAssetInfo.AssetInfo.AssetPath);
+ }
+ }
+ }
+ return result;
+ }
+
+ ///
+ /// 创建AssetBundleBuild类
+ ///
+ public UnityEditor.AssetBundleBuild CreatePipelineBuild()
+ {
+ // 注意:我们不再支持AssetBundle的变种机制
+ AssetBundleBuild build = new AssetBundleBuild();
+ build.assetBundleName = BundleName;
+ build.assetBundleVariant = string.Empty;
+ build.assetNames = GetAllMainAssetPaths();
+ return build;
+ }
+
+ ///
+ /// 获取所有写入补丁清单的资源
+ ///
+ public BuildAssetInfo[] GetAllManifestAssetInfos()
+ {
+ return MainAssets.Where(t => t.CollectorType == ECollectorType.MainAssetCollector).ToArray();
+ }
+
+ ///
+ /// 创建PackageBundle类
+ ///
+ internal PackageBundle CreatePackageBundle()
+ {
+ PackageBundle packageBundle = new PackageBundle();
+ packageBundle.BundleName = BundleName;
+ packageBundle.UnityCRC = PackageUnityCRC;
+ packageBundle.FileHash = PackageFileHash;
+ packageBundle.FileCRC = PackageFileCRC;
+ packageBundle.FileSize = PackageFileSize;
+ packageBundle.Encrypted = Encrypted;
+ return packageBundle;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildBundleInfo.cs.meta b/Editor/AssetBundleBuilder/BuildBundleInfo.cs.meta
new file mode 100644
index 0000000..d9e3552
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildBundleInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 826a9d7b4de0eba40b5c39b33747c011
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildMapContext.cs b/Editor/AssetBundleBuilder/BuildMapContext.cs
new file mode 100644
index 0000000..cfe0167
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildMapContext.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class BuildMapContext : IContextObject
+ {
+ ///
+ /// 资源包集合
+ ///
+ private readonly Dictionary _bundleInfoDic = new Dictionary(10000);
+
+ ///
+ /// 未被依赖的资源列表
+ ///
+ public readonly List IndependAssets = new List(1000);
+
+ ///
+ /// 参与构建的资源总数
+ /// 说明:包括主动收集的资源以及其依赖的所有资源
+ ///
+ public int AssetFileCount;
+
+ ///
+ /// 资源收集命令
+ ///
+ public CollectCommand Command { set; get; }
+
+ ///
+ /// 资源包信息列表
+ ///
+ public Dictionary.ValueCollection Collection
+ {
+ get
+ {
+ return _bundleInfoDic.Values;
+ }
+ }
+
+
+ ///
+ /// 添加一个打包资源
+ ///
+ public void PackAsset(BuildAssetInfo assetInfo)
+ {
+ string bundleName = assetInfo.BundleName;
+ if (string.IsNullOrEmpty(bundleName))
+ throw new Exception("Should never get here !");
+
+ if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo bundleInfo))
+ {
+ bundleInfo.PackAsset(assetInfo);
+ }
+ else
+ {
+ BuildBundleInfo newBundleInfo = new BuildBundleInfo(bundleName);
+ newBundleInfo.PackAsset(assetInfo);
+ _bundleInfoDic.Add(bundleName, newBundleInfo);
+ }
+ }
+
+ ///
+ /// 是否包含资源包
+ ///
+ public bool IsContainsBundle(string bundleName)
+ {
+ return _bundleInfoDic.ContainsKey(bundleName);
+ }
+
+ ///
+ /// 获取资源包信息,如果没找到返回NULL
+ ///
+ public BuildBundleInfo GetBundleInfo(string bundleName)
+ {
+ if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo result))
+ {
+ return result;
+ }
+ throw new Exception($"Should never get here ! Not found bundle : {bundleName}");
+ }
+
+ ///
+ /// 获取构建管线里需要的数据
+ ///
+ public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
+ {
+ List builds = new List(_bundleInfoDic.Count);
+ foreach (var bundleInfo in _bundleInfoDic.Values)
+ {
+ builds.Add(bundleInfo.CreatePipelineBuild());
+ }
+ return builds.ToArray();
+ }
+
+ ///
+ /// 创建着色器信息类
+ ///
+ public void CreateShadersBundleInfo(string shadersBundleName)
+ {
+ if (IsContainsBundle(shadersBundleName) == false)
+ {
+ var shaderBundleInfo = new BuildBundleInfo(shadersBundleName);
+ _bundleInfoDic.Add(shadersBundleName, shaderBundleInfo);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildMapContext.cs.meta b/Editor/AssetBundleBuilder/BuildMapContext.cs.meta
new file mode 100644
index 0000000..f70ef27
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildMapContext.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8229aa3f8a369204db5c368715191e2f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildParameters.cs b/Editor/AssetBundleBuilder/BuildParameters.cs
new file mode 100644
index 0000000..2ccb800
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildParameters.cs
@@ -0,0 +1,218 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 构建参数
+ ///
+ public abstract class BuildParameters
+ {
+ ///
+ /// 构建输出的根目录
+ ///
+ public string BuildOutputRoot;
+
+ ///
+ /// 内置文件的根目录
+ ///
+ public string BuildinFileRoot;
+
+ ///
+ /// 构建管线
+ ///
+ public string BuildPipeline
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// 构建的平台
+ ///
+ public BuildTarget BuildTarget;
+
+ ///
+ /// 构建模式
+ ///
+ public EBuildMode BuildMode;
+
+ ///
+ /// 构建的包裹名称
+ ///
+ public string PackageName;
+
+ ///
+ /// 构建的包裹版本
+ ///
+ public string PackageVersion;
+
+
+ ///
+ /// 是否启用共享资源打包
+ ///
+ public bool EnableSharePackRule = false;
+
+ ///
+ /// 验证构建结果
+ ///
+ public bool VerifyBuildingResult = false;
+
+ ///
+ /// 资源包名称样式
+ ///
+ public EFileNameStyle FileNameStyle;
+
+ ///
+ /// 内置文件的拷贝选项
+ ///
+ public EBuildinFileCopyOption BuildinFileCopyOption;
+
+ ///
+ /// 内置文件的拷贝参数
+ ///
+ public string BuildinFileCopyParams;
+
+ ///
+ /// 资源包加密服务类
+ ///
+ public IEncryptionServices EncryptionServices;
+
+
+ private string _pipelineOutputDirectory = string.Empty;
+ private string _packageOutputDirectory = string.Empty;
+ private string _packageRootDirectory = string.Empty;
+ private string _buildinRootDirectory = string.Empty;
+
+ ///
+ /// 检测构建参数是否合法
+ ///
+ public virtual void CheckBuildParameters()
+ {
+ // 检测当前是否正在构建资源包
+ if (UnityEditor.BuildPipeline.isBuildingPlayer)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.ThePipelineIsBuiding, "The pipeline is buiding, please try again after finish !");
+ throw new Exception(message);
+ }
+
+ // 检测是否有未保存场景
+ if (BuildMode != EBuildMode.SimulateBuild)
+ {
+ if (EditorTools.HasDirtyScenes())
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.FoundUnsavedScene, "Found unsaved scene !");
+ throw new Exception(message);
+ }
+ }
+
+ // 检测构建参数合法性
+ if (BuildTarget == BuildTarget.NoTarget)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NoBuildTarget, "Please select the build target platform !");
+ throw new Exception(message);
+ }
+ if (string.IsNullOrEmpty(PackageName))
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.PackageNameIsNullOrEmpty, "Package name is null or empty !");
+ throw new Exception(message);
+ }
+ if (string.IsNullOrEmpty(PackageVersion))
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.PackageVersionIsNullOrEmpty, "Package version is null or empty !");
+ throw new Exception(message);
+ }
+ if (string.IsNullOrEmpty(BuildOutputRoot))
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildOutputRootIsNullOrEmpty, "Build output root is null or empty !");
+ throw new Exception(message);
+ }
+ if (string.IsNullOrEmpty(BuildinFileRoot))
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildinFileRootIsNullOrEmpty, "Buildin file root is null or empty !");
+ throw new Exception(message);
+ }
+
+ // 强制构建删除包裹目录
+ if (BuildMode == EBuildMode.ForceRebuild)
+ {
+ string packageRootDirectory = GetPackageRootDirectory();
+ if (EditorTools.DeleteDirectory(packageRootDirectory))
+ {
+ BuildLogger.Log($"Delete package root directory: {packageRootDirectory}");
+ }
+ }
+
+ // 检测包裹输出目录是否存在
+ if (BuildMode != EBuildMode.SimulateBuild)
+ {
+ string packageOutputDirectory = GetPackageOutputDirectory();
+ if (Directory.Exists(packageOutputDirectory))
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.PackageOutputDirectoryExists, $"Package outout directory exists: {packageOutputDirectory}");
+ throw new Exception(message);
+ }
+ }
+
+ // 如果输出目录不存在
+ string pipelineOutputDirectory = GetPipelineOutputDirectory();
+ if (EditorTools.CreateDirectory(pipelineOutputDirectory))
+ {
+ BuildLogger.Log($"Create pipeline output directory: {pipelineOutputDirectory}");
+ }
+ }
+
+
+ ///
+ /// 获取构建管线的输出目录
+ ///
+ ///
+ public virtual string GetPipelineOutputDirectory()
+ {
+ if (string.IsNullOrEmpty(_pipelineOutputDirectory))
+ {
+ _pipelineOutputDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{YooAssetSettings.OutputFolderName}";
+ }
+ return _pipelineOutputDirectory;
+ }
+
+ ///
+ /// 获取本次构建的补丁输出目录
+ ///
+ public virtual string GetPackageOutputDirectory()
+ {
+ if (string.IsNullOrEmpty(_packageOutputDirectory))
+ {
+ _packageOutputDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{PackageVersion}";
+ }
+ return _packageOutputDirectory;
+ }
+
+ ///
+ /// 获取本次构建的补丁根目录
+ ///
+ public virtual string GetPackageRootDirectory()
+ {
+ if (string.IsNullOrEmpty(_packageRootDirectory))
+ {
+ _packageRootDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}";
+ }
+ return _packageRootDirectory;
+ }
+
+ ///
+ /// 获取内置资源的根目录
+ ///
+ public virtual string GetBuildinRootDirectory()
+ {
+ if (string.IsNullOrEmpty(_buildinRootDirectory))
+ {
+ _buildinRootDirectory = $"{BuildinFileRoot}/{PackageName}";
+ }
+ return _buildinRootDirectory;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildParameters.cs.meta b/Editor/AssetBundleBuilder/BuildParameters.cs.meta
new file mode 100644
index 0000000..d2a2f3c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildParameters.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 98bb314dc26ba184fbb9e9fdcdb58a1d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildParametersContext.cs b/Editor/AssetBundleBuilder/BuildParametersContext.cs
new file mode 100644
index 0000000..07aa652
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildParametersContext.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class BuildParametersContext : IContextObject
+ {
+ ///
+ /// 构建参数
+ ///
+ public BuildParameters Parameters { private set; get; }
+
+
+ public BuildParametersContext(BuildParameters parameters)
+ {
+ Parameters = parameters;
+ }
+
+ ///
+ /// 检测构建参数是否合法
+ ///
+ public void CheckBuildParameters()
+ {
+ Parameters.CheckBuildParameters();
+ }
+
+ ///
+ /// 获取构建管线的输出目录
+ ///
+ ///
+ public string GetPipelineOutputDirectory()
+ {
+ return Parameters.GetPipelineOutputDirectory();
+ }
+
+ ///
+ /// 获取本次构建的补丁输出目录
+ ///
+ public string GetPackageOutputDirectory()
+ {
+ return Parameters.GetPackageOutputDirectory();
+ }
+
+ ///
+ /// 获取本次构建的补丁根目录
+ ///
+ public string GetPackageRootDirectory()
+ {
+ return Parameters.GetPackageRootDirectory();
+ }
+
+ ///
+ /// 获取内置资源的根目录
+ ///
+ public string GetBuildinRootDirectory()
+ {
+ return Parameters.GetBuildinRootDirectory();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildParametersContext.cs.meta b/Editor/AssetBundleBuilder/BuildParametersContext.cs.meta
new file mode 100644
index 0000000..665fc41
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildParametersContext.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b84510feab7cbe44a9b6d8ef0b3f559c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline.meta b/Editor/AssetBundleBuilder/BuildPipeline.meta
new file mode 100644
index 0000000..29b3e28
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 431722e1bca52d448825f603789d7e4b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks.meta
new file mode 100644
index 0000000..863df44
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 254f430e0264bd84387878f8d7280e44
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs
new file mode 100644
index 0000000..4579410
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskCopyBuildinFiles
+ {
+ ///
+ /// 拷贝首包资源文件
+ ///
+ internal void CopyBuildinFilesToStreaming(BuildParametersContext buildParametersContext, PackageManifest manifest)
+ {
+ EBuildinFileCopyOption copyOption = buildParametersContext.Parameters.BuildinFileCopyOption;
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
+ string buildPackageName = buildParametersContext.Parameters.PackageName;
+ string buildPackageVersion = buildParametersContext.Parameters.PackageVersion;
+
+ // 清空内置文件的目录
+ if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.ClearAndCopyByTags)
+ {
+ EditorTools.ClearFolder(buildinRootDirectory);
+ }
+
+ // 拷贝补丁清单文件
+ {
+ string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildPackageName, buildPackageVersion);
+ string sourcePath = $"{packageOutputDirectory}/{fileName}";
+ string destPath = $"{buildinRootDirectory}/{fileName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝补丁清单哈希文件
+ {
+ string fileName = YooAssetSettingsData.GetPackageHashFileName(buildPackageName, buildPackageVersion);
+ string sourcePath = $"{packageOutputDirectory}/{fileName}";
+ string destPath = $"{buildinRootDirectory}/{fileName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝补丁清单版本文件
+ {
+ string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildPackageName);
+ string sourcePath = $"{packageOutputDirectory}/{fileName}";
+ string destPath = $"{buildinRootDirectory}/{fileName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝文件列表(所有文件)
+ if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.OnlyCopyAll)
+ {
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
+ string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+ }
+
+ // 拷贝文件列表(带标签的文件)
+ if (copyOption == EBuildinFileCopyOption.ClearAndCopyByTags || copyOption == EBuildinFileCopyOption.OnlyCopyByTags)
+ {
+ string[] tags = buildParametersContext.Parameters.BuildinFileCopyParams.Split(';');
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ if (packageBundle.HasTag(tags) == false)
+ continue;
+ string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
+ string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+ }
+
+ // 刷新目录
+ AssetDatabase.Refresh();
+ BuildLogger.Log($"Buildin files copy complete: {buildinRootDirectory}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs.meta
new file mode 100644
index 0000000..6ac8176
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCopyBuildinFiles.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5c77e17c3a3a57548a218f1cd26f5a55
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs
new file mode 100644
index 0000000..23120ef
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class ManifestContext : IContextObject
+ {
+ internal PackageManifest Manifest;
+ }
+
+ public abstract class TaskCreateManifest
+ {
+ private readonly Dictionary _cachedBundleID = new Dictionary(10000);
+ private readonly Dictionary> _cacheBundleTags = new Dictionary>(10000);
+
+ ///
+ /// 创建补丁清单文件到输出目录
+ ///
+ protected void CreateManifestFile(BuildContext context)
+ {
+ var buildMapContext = context.GetContextObject();
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters;
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+
+ // 创建新补丁清单
+ PackageManifest manifest = new PackageManifest();
+ manifest.FileVersion = YooAssetSettings.ManifestFileVersion;
+ manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
+ manifest.LocationToLower = buildMapContext.Command.LocationToLower;
+ manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
+ manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
+ manifest.BuildPipeline = buildParameters.BuildPipeline;
+ manifest.PackageName = buildParameters.PackageName;
+ manifest.PackageVersion = buildParameters.PackageVersion;
+ manifest.BundleList = GetAllPackageBundle(buildMapContext);
+ manifest.AssetList = GetAllPackageAsset(buildMapContext);
+
+ if (buildParameters.BuildMode != EBuildMode.SimulateBuild)
+ {
+ // 处理资源包的依赖列表
+ ProcessBundleDepends(context, manifest);
+
+ // 处理资源包的标签集合
+ ProcessBundleTags(manifest);
+ }
+
+ // 创建补丁清单文本文件
+ {
+ string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string filePath = $"{packageOutputDirectory}/{fileName}";
+ ManifestTools.SerializeToJson(filePath, manifest);
+ BuildLogger.Log($"Create package manifest file: {filePath}");
+ }
+
+ // 创建补丁清单二进制文件
+ string packageHash;
+ {
+ string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string filePath = $"{packageOutputDirectory}/{fileName}";
+ ManifestTools.SerializeToBinary(filePath, manifest);
+ packageHash = HashUtility.FileMD5(filePath);
+ BuildLogger.Log($"Create package manifest file: {filePath}");
+
+ ManifestContext manifestContext = new ManifestContext();
+ byte[] bytesData = FileUtility.ReadAllBytes(filePath);
+ manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData);
+ context.SetContextObject(manifestContext);
+ }
+
+ // 创建补丁清单哈希文件
+ {
+ string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string filePath = $"{packageOutputDirectory}/{fileName}";
+ FileUtility.WriteAllText(filePath, packageHash);
+ BuildLogger.Log($"Create package manifest hash file: {filePath}");
+ }
+
+ // 创建补丁清单版本文件
+ {
+ string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
+ string filePath = $"{packageOutputDirectory}/{fileName}";
+ FileUtility.WriteAllText(filePath, buildParameters.PackageVersion);
+ BuildLogger.Log($"Create package manifest version file: {filePath}");
+ }
+ }
+
+ ///
+ /// 获取资源包的依赖集合
+ ///
+ protected abstract string[] GetBundleDepends(BuildContext context, string bundleName);
+
+ ///
+ /// 获取主资源对象列表
+ ///
+ private List GetAllPackageAsset(BuildMapContext buildMapContext)
+ {
+ List result = new List(1000);
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ var assetInfos = bundleInfo.GetAllManifestAssetInfos();
+ foreach (var assetInfo in assetInfos)
+ {
+ PackageAsset packageAsset = new PackageAsset();
+ packageAsset.Address = buildMapContext.Command.EnableAddressable ? assetInfo.Address : string.Empty;
+ packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath;
+ packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty;
+ packageAsset.AssetTags = assetInfo.AssetTags.ToArray();
+ packageAsset.BundleID = GetCachedBundleID(assetInfo.BundleName);
+ result.Add(packageAsset);
+ }
+ }
+ return result;
+ }
+
+ ///
+ /// 获取资源包列表
+ ///
+ private List GetAllPackageBundle(BuildMapContext buildMapContext)
+ {
+ List result = new List(1000);
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ var packageBundle = bundleInfo.CreatePackageBundle();
+ result.Add(packageBundle);
+ }
+
+ // 注意:缓存资源包索引
+ for (int index = 0; index < result.Count; index++)
+ {
+ string bundleName = result[index].BundleName;
+ _cachedBundleID.Add(bundleName, index);
+ }
+
+ return result;
+ }
+
+ ///
+ /// 处理资源包的依赖集合
+ ///
+ private void ProcessBundleDepends(BuildContext context, PackageManifest manifest)
+ {
+ // 查询引擎生成的资源包依赖关系,然后记录到清单
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ int mainBundleID = GetCachedBundleID(packageBundle.BundleName);
+ var depends = GetBundleDepends(context, packageBundle.BundleName);
+ List dependIDs = new List(depends.Length);
+ foreach (var dependBundleName in depends)
+ {
+ int bundleID = GetCachedBundleID(dependBundleName);
+ if (bundleID != mainBundleID)
+ dependIDs.Add(bundleID);
+ }
+ packageBundle.DependIDs = dependIDs.ToArray();
+ }
+ }
+
+ ///
+ /// 处理资源包的标签集合
+ ///
+ private void ProcessBundleTags(PackageManifest manifest)
+ {
+ // 将主资源的标签信息传染给其依赖的资源包集合
+ foreach (var packageAsset in manifest.AssetList)
+ {
+ var assetTags = packageAsset.AssetTags;
+ int bundleID = packageAsset.BundleID;
+ CacheBundleTags(bundleID, assetTags);
+
+ var packageBundle = manifest.BundleList[bundleID];
+ foreach (var dependBundleID in packageBundle.DependIDs)
+ {
+ CacheBundleTags(dependBundleID, assetTags);
+ }
+ }
+
+ for (int index = 0; index < manifest.BundleList.Count; index++)
+ {
+ var packageBundle = manifest.BundleList[index];
+ if (_cacheBundleTags.ContainsKey(index))
+ {
+ packageBundle.Tags = _cacheBundleTags[index].ToArray();
+ }
+ else
+ {
+ // 注意:SBP构建管线会自动剔除一些冗余资源的引用关系,导致游离资源包没有被任何主资源包引用。
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundStrayBundle, $"Found stray bundle ! Bundle ID : {index} Bundle name : {packageBundle.BundleName}");
+ BuildLogger.Warning(warning);
+ }
+ }
+ }
+ private void CacheBundleTags(int bundleID, string[] assetTags)
+ {
+ if (_cacheBundleTags.ContainsKey(bundleID) == false)
+ _cacheBundleTags.Add(bundleID, new HashSet());
+
+ foreach (var assetTag in assetTags)
+ {
+ if (_cacheBundleTags[bundleID].Contains(assetTag) == false)
+ _cacheBundleTags[bundleID].Add(assetTag);
+ }
+ }
+
+ ///
+ /// 获取资源包的索引ID
+ ///
+ private int GetCachedBundleID(string bundleName)
+ {
+ if (_cachedBundleID.TryGetValue(bundleName, out int value) == false)
+ {
+ throw new Exception($"Should never get here ! Not found bundle ID : {bundleName}");
+ }
+ return value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs.meta
new file mode 100644
index 0000000..53cf77f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateManifest.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 566c37f5a59f2e84397a9527981a7310
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs
new file mode 100644
index 0000000..56051f5
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateReport
+ {
+ protected void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext, ManifestContext manifestContext)
+ {
+ var buildParameters = buildParametersContext.Parameters;
+
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ PackageManifest manifest = manifestContext.Manifest;
+ BuildReport buildReport = new BuildReport();
+
+ // 概述信息
+ {
+#if UNITY_2019_4_OR_NEWER
+ UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(BuildReport).Assembly);
+ if (packageInfo != null)
+ buildReport.Summary.YooVersion = packageInfo.version;
+#endif
+ buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion;
+ buildReport.Summary.BuildDate = DateTime.Now.ToString();
+ buildReport.Summary.BuildSeconds = BuildRunner.TotalSeconds;
+ buildReport.Summary.BuildTarget = buildParameters.BuildTarget;
+ buildReport.Summary.BuildPipeline = buildParameters.BuildPipeline;
+ buildReport.Summary.BuildMode = buildParameters.BuildMode;
+ buildReport.Summary.BuildPackageName = buildParameters.PackageName;
+ buildReport.Summary.BuildPackageVersion = buildParameters.PackageVersion;
+
+ // 收集器配置
+ buildReport.Summary.UniqueBundleName = buildMapContext.Command.UniqueBundleName;
+ buildReport.Summary.EnableAddressable = buildMapContext.Command.EnableAddressable;
+ buildReport.Summary.LocationToLower = buildMapContext.Command.LocationToLower;
+ buildReport.Summary.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
+ buildReport.Summary.IgnoreDefaultType = buildMapContext.Command.IgnoreDefaultType;
+ buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders;
+
+ // 构建参数
+ buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;
+ buildReport.Summary.EncryptionClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName;
+ if (buildParameters.BuildPipeline == nameof(BuiltinBuildPipeline))
+ {
+ var builtinBuildParameters = buildParameters as BuiltinBuildParameters;
+ buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
+ buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
+ buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
+ buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
+ }
+ else if (buildParameters.BuildPipeline == nameof(ScriptableBuildPipeline))
+ {
+ var scriptableBuildParameters = buildParameters as ScriptableBuildParameters;
+ buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
+ buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
+ buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
+ buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
+ }
+ else
+ {
+ buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
+ buildReport.Summary.CompressOption = ECompressOption.Uncompressed;
+ buildReport.Summary.DisableWriteTypeTree = false;
+ buildReport.Summary.IgnoreTypeTreeChanges = false;
+ }
+
+ // 构建结果
+ buildReport.Summary.AssetFileTotalCount = buildMapContext.AssetFileCount;
+ buildReport.Summary.MainAssetTotalCount = GetMainAssetCount(manifest);
+ buildReport.Summary.AllBundleTotalCount = GetAllBundleCount(manifest);
+ buildReport.Summary.AllBundleTotalSize = GetAllBundleSize(manifest);
+ buildReport.Summary.EncryptedBundleTotalCount = GetEncryptedBundleCount(manifest);
+ buildReport.Summary.EncryptedBundleTotalSize = GetEncryptedBundleSize(manifest);
+ }
+
+ // 资源对象列表
+ buildReport.AssetInfos = new List(manifest.AssetList.Count);
+ foreach (var packageAsset in manifest.AssetList)
+ {
+ var mainBundle = manifest.BundleList[packageAsset.BundleID];
+ ReportAssetInfo reportAssetInfo = new ReportAssetInfo();
+ reportAssetInfo.Address = packageAsset.Address;
+ reportAssetInfo.AssetPath = packageAsset.AssetPath;
+ reportAssetInfo.AssetTags = packageAsset.AssetTags;
+ reportAssetInfo.AssetGUID = AssetDatabase.AssetPathToGUID(packageAsset.AssetPath);
+ reportAssetInfo.MainBundleName = mainBundle.BundleName;
+ reportAssetInfo.MainBundleSize = mainBundle.FileSize;
+ reportAssetInfo.DependAssets = GetDependAssets(buildMapContext, mainBundle.BundleName, packageAsset.AssetPath);
+ buildReport.AssetInfos.Add(reportAssetInfo);
+ }
+
+ // 资源包列表
+ buildReport.BundleInfos = new List(manifest.BundleList.Count);
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ ReportBundleInfo reportBundleInfo = new ReportBundleInfo();
+ reportBundleInfo.BundleName = packageBundle.BundleName;
+ reportBundleInfo.FileName = packageBundle.FileName;
+ reportBundleInfo.FileHash = packageBundle.FileHash;
+ reportBundleInfo.FileCRC = packageBundle.FileCRC;
+ reportBundleInfo.FileSize = packageBundle.FileSize;
+ reportBundleInfo.Encrypted = packageBundle.Encrypted;
+ reportBundleInfo.Tags = packageBundle.Tags;
+ reportBundleInfo.DependBundles = GetDependBundles(manifest, packageBundle);
+ reportBundleInfo.AllBuiltinAssets = GetAllBuiltinAssets(buildMapContext, packageBundle.BundleName);
+ buildReport.BundleInfos.Add(reportBundleInfo);
+ }
+
+ // 其它资源列表
+ buildReport.IndependAssets = new List(buildMapContext.IndependAssets);
+
+ // 序列化文件
+ string fileName = YooAssetSettingsData.GetReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
+ string filePath = $"{packageOutputDirectory}/{fileName}";
+ BuildReport.Serialize(filePath, buildReport);
+ BuildLogger.Log($"Create build report file: {filePath}");
+ }
+
+ ///
+ /// 获取资源对象依赖的所有资源包
+ ///
+ private List GetDependBundles(PackageManifest manifest, PackageBundle packageBundle)
+ {
+ List dependBundles = new List(packageBundle.DependIDs.Length);
+ foreach (int index in packageBundle.DependIDs)
+ {
+ string dependBundleName = manifest.BundleList[index].BundleName;
+ dependBundles.Add(dependBundleName);
+ }
+ return dependBundles;
+ }
+
+ ///
+ /// 获取资源对象依赖的其它所有资源
+ ///
+ private List GetDependAssets(BuildMapContext buildMapContext, string bundleName, string assetPath)
+ {
+ List result = new List();
+ var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
+ {
+ BuildAssetInfo findAssetInfo = null;
+ foreach (var buildAsset in bundleInfo.MainAssets)
+ {
+ if (buildAsset.AssetInfo.AssetPath == assetPath)
+ {
+ findAssetInfo = buildAsset;
+ break;
+ }
+ }
+ if (findAssetInfo == null)
+ {
+ throw new Exception($"Should never get here ! Not found asset {assetPath} in bunlde {bundleName}");
+ }
+ foreach (var dependAssetInfo in findAssetInfo.AllDependAssetInfos)
+ {
+ result.Add(dependAssetInfo.AssetInfo.AssetPath);
+ }
+ }
+ return result;
+ }
+
+ ///
+ /// 获取该资源包内的所有资源
+ ///
+ private List GetAllBuiltinAssets(BuildMapContext buildMapContext, string bundleName)
+ {
+ var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
+ return bundleInfo.GetAllBuiltinAssetPaths();
+ }
+
+ private int GetMainAssetCount(PackageManifest manifest)
+ {
+ return manifest.AssetList.Count;
+ }
+ private int GetAllBundleCount(PackageManifest manifest)
+ {
+ return manifest.BundleList.Count;
+ }
+ private long GetAllBundleSize(PackageManifest manifest)
+ {
+ long fileBytes = 0;
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ fileBytes += packageBundle.FileSize;
+ }
+ return fileBytes;
+ }
+ private int GetEncryptedBundleCount(PackageManifest manifest)
+ {
+ int fileCount = 0;
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ if (packageBundle.Encrypted)
+ fileCount++;
+ }
+ return fileCount;
+ }
+ private long GetEncryptedBundleSize(PackageManifest manifest)
+ {
+ long fileBytes = 0;
+ foreach (var packageBundle in manifest.BundleList)
+ {
+ if (packageBundle.Encrypted)
+ fileBytes += packageBundle.FileSize;
+ }
+ return fileBytes;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs.meta
new file mode 100644
index 0000000..b37114b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskCreateReport.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bd12814185b4c7044b0afd59f9c1c948
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs
new file mode 100644
index 0000000..d430ae1
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskEncryption
+ {
+ ///
+ /// 加密文件
+ ///
+ public void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
+ {
+ var encryptionServices = buildParametersContext.Parameters.EncryptionServices;
+ if (encryptionServices == null)
+ return;
+
+ if (encryptionServices.GetType() == typeof(EncryptionNone))
+ return;
+
+ int progressValue = 0;
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ EncryptFileInfo fileInfo = new EncryptFileInfo();
+ fileInfo.BundleName = bundleInfo.BundleName;
+ fileInfo.FilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
+ var encryptResult = encryptionServices.Encrypt(fileInfo);
+ if (encryptResult.Encrypted)
+ {
+ string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt";
+ FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedData);
+ bundleInfo.EncryptedFilePath = filePath;
+ bundleInfo.Encrypted = true;
+ BuildLogger.Log($"Bundle file encryption complete: {filePath}");
+ }
+ else
+ {
+ bundleInfo.Encrypted = false;
+ }
+
+ // 进度条
+ EditorTools.DisplayProgressBar("Encrypting bundle", ++progressValue, buildMapContext.Collection.Count);
+ }
+ EditorTools.ClearProgressBar();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs.meta
new file mode 100644
index 0000000..6561a79
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskEncryption.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c78d471226b9c8d429a2d962370f480b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs
new file mode 100644
index 0000000..6e78c05
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs
@@ -0,0 +1,229 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskGetBuildMap
+ {
+ ///
+ /// 生成资源构建上下文
+ ///
+ public BuildMapContext CreateBuildMap(BuildParameters buildParameters)
+ {
+ BuildMapContext context = new BuildMapContext();
+ var buildMode = buildParameters.BuildMode;
+ var packageName = buildParameters.PackageName;
+
+ Dictionary allBuildAssetInfos = new Dictionary(1000);
+
+ // 1. 获取所有收集器收集的资源
+ var collectResult = AssetBundleCollectorSettingData.Setting.GetPackageAssets(buildMode, packageName);
+ List allCollectAssets = collectResult.CollectAssets;
+
+ // 2. 剔除未被引用的依赖项资源
+ RemoveZeroReferenceAssets(context, allCollectAssets);
+
+ // 3. 录入所有收集器主动收集的资源
+ foreach (var collectAssetInfo in allCollectAssets)
+ {
+ if (allBuildAssetInfos.ContainsKey(collectAssetInfo.AssetInfo.AssetPath))
+ {
+ throw new Exception($"Should never get here !");
+ }
+
+ if (collectAssetInfo.CollectorType != ECollectorType.MainAssetCollector)
+ {
+ if (collectAssetInfo.AssetTags.Count > 0)
+ {
+ collectAssetInfo.AssetTags.Clear();
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.RemoveInvalidTags, $"Remove asset tags that don't work, see the asset collector type : {collectAssetInfo.AssetInfo.AssetPath}");
+ BuildLogger.Warning(warning);
+ }
+ }
+
+ var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.CollectorType, collectAssetInfo.BundleName, collectAssetInfo.Address, collectAssetInfo.AssetInfo);
+ buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
+ allBuildAssetInfos.Add(collectAssetInfo.AssetInfo.AssetPath, buildAssetInfo);
+ }
+
+ // 4. 录入所有收集资源依赖的其它资源
+ foreach (var collectAssetInfo in allCollectAssets)
+ {
+ string bundleName = collectAssetInfo.BundleName;
+ foreach (var dependAsset in collectAssetInfo.DependAssets)
+ {
+ if (allBuildAssetInfos.ContainsKey(dependAsset.AssetPath))
+ {
+ allBuildAssetInfos[dependAsset.AssetPath].AddReferenceBundleName(bundleName);
+ }
+ else
+ {
+ var buildAssetInfo = new BuildAssetInfo(dependAsset);
+ buildAssetInfo.AddReferenceBundleName(bundleName);
+ allBuildAssetInfos.Add(dependAsset.AssetPath, buildAssetInfo);
+ }
+ }
+ }
+
+ // 5. 填充所有收集资源的依赖列表
+ foreach (var collectAssetInfo in allCollectAssets)
+ {
+ var dependAssetInfos = new List(collectAssetInfo.DependAssets.Count);
+ foreach (var dependAsset in collectAssetInfo.DependAssets)
+ {
+ if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out BuildAssetInfo value))
+ dependAssetInfos.Add(value);
+ else
+ throw new Exception("Should never get here !");
+ }
+ allBuildAssetInfos[collectAssetInfo.AssetInfo.AssetPath].SetDependAssetInfos(dependAssetInfos);
+ }
+
+ // 6. 自动收集所有依赖的着色器
+ if (collectResult.Command.AutoCollectShaders)
+ {
+ // 获取着色器打包规则结果
+ PackRuleResult shaderPackRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
+ string shaderBundleName = shaderPackRuleResult.GetBundleName(collectResult.Command.PackageName, collectResult.Command.UniqueBundleName);
+ foreach (var buildAssetInfo in allBuildAssetInfos.Values)
+ {
+ if (buildAssetInfo.CollectorType == ECollectorType.None)
+ {
+ if (buildAssetInfo.AssetInfo.IsShaderAsset())
+ {
+ buildAssetInfo.SetBundleName(shaderBundleName);
+ }
+ }
+ }
+ }
+
+ // 7. 计算共享资源的包名
+ if (buildParameters.EnableSharePackRule)
+ {
+ PreProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
+ foreach (var buildAssetInfo in allBuildAssetInfos.Values)
+ {
+ if (buildAssetInfo.HasBundleName() == false)
+ {
+ PackRuleResult packRuleResult = GetShareBundleName(buildAssetInfo);
+ if (packRuleResult.IsValid())
+ {
+ string shareBundleName = packRuleResult.GetShareBundleName(collectResult.Command.PackageName, collectResult.Command.UniqueBundleName);
+ buildAssetInfo.SetBundleName(shareBundleName);
+ }
+ }
+ }
+ PostProcessPackShareBundle();
+ }
+
+ // 8. 记录关键信息
+ context.AssetFileCount = allBuildAssetInfos.Count;
+ context.Command = collectResult.Command;
+
+ // 9. 移除不参与构建的资源
+ List removeBuildList = new List();
+ foreach (var buildAssetInfo in allBuildAssetInfos.Values)
+ {
+ if (buildAssetInfo.HasBundleName() == false)
+ removeBuildList.Add(buildAssetInfo);
+ }
+ foreach (var removeValue in removeBuildList)
+ {
+ allBuildAssetInfos.Remove(removeValue.AssetInfo.AssetPath);
+ }
+
+ // 10. 构建资源列表
+ var allPackAssets = allBuildAssetInfos.Values.ToList();
+ if (allPackAssets.Count == 0)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.PackAssetListIsEmpty, "The pack asset info is empty !");
+ throw new Exception(message);
+ }
+ foreach (var assetInfo in allPackAssets)
+ {
+ context.PackAsset(assetInfo);
+ }
+
+ return context;
+ }
+ private void RemoveZeroReferenceAssets(BuildMapContext context, List allCollectAssets)
+ {
+ // 1. 检测依赖资源收集器是否存在
+ if (allCollectAssets.Exists(x => x.CollectorType == ECollectorType.DependAssetCollector) == false)
+ return;
+
+ // 2. 获取所有主资源的依赖资源集合
+ HashSet allDependAsset = new HashSet();
+ foreach (var collectAsset in allCollectAssets)
+ {
+ var collectorType = collectAsset.CollectorType;
+ if (collectorType == ECollectorType.MainAssetCollector || collectorType == ECollectorType.StaticAssetCollector)
+ {
+ foreach (var dependAsset in collectAsset.DependAssets)
+ {
+ if (allDependAsset.Contains(dependAsset.AssetPath) == false)
+ allDependAsset.Add(dependAsset.AssetPath);
+ }
+ }
+ }
+
+ // 3. 找出所有零引用的依赖资源集合
+ List removeList = new List();
+ foreach (var collectAssetInfo in allCollectAssets)
+ {
+ var collectorType = collectAssetInfo.CollectorType;
+ if (collectorType == ECollectorType.DependAssetCollector)
+ {
+ if (allDependAsset.Contains(collectAssetInfo.AssetInfo.AssetPath) == false)
+ removeList.Add(collectAssetInfo);
+ }
+ }
+
+ // 4. 移除所有零引用的依赖资源
+ foreach (var removeValue in removeList)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundUndependedAsset, $"Found undepended asset and remove it : {removeValue.AssetInfo.AssetPath}");
+ BuildLogger.Warning(warning);
+
+ var independAsset = new ReportIndependAsset();
+ independAsset.AssetPath = removeValue.AssetInfo.AssetPath;
+ independAsset.AssetGUID = removeValue.AssetInfo.AssetGUID;
+ independAsset.AssetType = removeValue.AssetInfo.AssetType.ToString();
+ independAsset.FileSize = FileUtility.GetFileSize(removeValue.AssetInfo.AssetPath);
+ context.IndependAssets.Add(independAsset);
+
+ allCollectAssets.Remove(removeValue);
+ }
+ }
+
+ #region 共享资源打包规则
+ ///
+ /// 共享资源打包前置处理
+ ///
+ protected virtual void PreProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary allBuildAssetInfos)
+ {
+ }
+
+ ///
+ /// 共享资源打包后置处理
+ ///
+ protected virtual void PostProcessPackShareBundle()
+ {
+ }
+
+ ///
+ /// 获取共享资源包名称
+ ///
+ protected virtual PackRuleResult GetShareBundleName(BuildAssetInfo buildAssetInfo)
+ {
+ string bundleName = Path.GetDirectoryName(buildAssetInfo.AssetInfo.AssetPath);
+ PackRuleResult result = new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension);
+ return result;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs.meta
new file mode 100644
index 0000000..9ec942f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskGetBuildMap.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: baee18c5c7b76584b90413bf20fdae9a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs
new file mode 100644
index 0000000..08a7d7d
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public abstract class TaskUpdateBundleInfo
+ {
+ public void UpdateBundleInfo(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ int outputNameStyle = (int)buildParametersContext.Parameters.FileNameStyle;
+
+ // 1.检测文件名长度
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ // NOTE:检测文件名长度不要超过260字符。
+ string fileName = bundleInfo.BundleName;
+ if (fileName.Length >= 260)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.CharactersOverTheLimit, $"Bundle file name character count exceeds limit : {fileName}");
+ throw new Exception(message);
+ }
+ }
+
+ // 2.更新构建输出的文件路径
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ bundleInfo.BuildOutputFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
+ if (bundleInfo.Encrypted)
+ bundleInfo.PackageSourceFilePath = bundleInfo.EncryptedFilePath;
+ else
+ bundleInfo.PackageSourceFilePath = bundleInfo.BuildOutputFilePath;
+ }
+
+ // 3.更新文件其它信息
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
+ bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
+ bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, buildParametersContext);
+ bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, buildParametersContext);
+ bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, buildParametersContext);
+ }
+
+ // 4.更新补丁包输出的文件路径
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ string bundleName = bundleInfo.BundleName;
+ string fileHash = bundleInfo.PackageFileHash;
+ string fileExtension = ManifestTools.GetRemoteBundleFileExtension(bundleName);
+ string fileName = ManifestTools.GetRemoteBundleFileName(outputNameStyle, bundleName, fileExtension, fileHash);
+ bundleInfo.PackageDestFilePath = $"{packageOutputDirectory}/{fileName}";
+ }
+ }
+
+ protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
+ protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
+ protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
+ protected abstract string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
+ protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
+
+ protected string GetFilePathTempHash(string filePath)
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(filePath);
+ return HashUtility.BytesMD5(bytes);
+
+ // 注意:在文件路径的哈希值冲突的情况下,可以使用下面的方法
+ //return $"{HashUtility.BytesMD5(bytes)}-{Guid.NewGuid():N}";
+ }
+
+ protected long GetBundleTempSize(BuildBundleInfo bundleInfo)
+ {
+ long tempSize = 0;
+
+ var assetPaths = bundleInfo.GetAllMainAssetPaths();
+ foreach (var assetPath in assetPaths)
+ {
+ long size = FileUtility.GetFileSize(assetPath);
+ tempSize += size;
+ }
+
+ if (tempSize == 0)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BundleTempSizeIsZero, $"Bundle temp size is zero, check bundle main asset list : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ return tempSize;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs.meta
new file mode 100644
index 0000000..3cab95f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BaseTasks/TaskUpdateBundleInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4882f54fbf0bcb04680fb581deae4889
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline.meta
new file mode 100644
index 0000000..2c37be7
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5c0a1b7e213a63047994bbf419867c64
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks.meta
new file mode 100644
index 0000000..3679054
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 950b38743cf6b74419af76ab327206ed
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs
new file mode 100644
index 0000000..f15882a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskBuilding_BBP : IBuildTask
+ {
+ public class BuildResultContext : IContextObject
+ {
+ public AssetBundleManifest UnityManifest;
+ }
+
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var builtinBuildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
+
+ // 模拟构建模式下跳过引擎构建
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return;
+
+ // 开始构建
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ BuildAssetBundleOptions buildOptions = builtinBuildParameters.GetBundleBuildOptions();
+ AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), buildOptions, buildParametersContext.Parameters.BuildTarget);
+ if (unityManifest == null)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, "UnityEngine build failed !");
+ throw new Exception(message);
+ }
+
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ string unityOutputManifestFilePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}";
+ if (System.IO.File.Exists(unityOutputManifestFilePath) == false)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFatal, $"Not found output {nameof(AssetBundleManifest)} file : {unityOutputManifestFilePath}");
+ throw new Exception(message);
+ }
+ }
+
+ BuildLogger.Log("UnityEngine build success !");
+ BuildResultContext buildResultContext = new BuildResultContext();
+ buildResultContext.UnityManifest = unityManifest;
+ context.SetContextObject(buildResultContext);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs.meta
new file mode 100644
index 0000000..8db983f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskBuilding_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d10c8f8b9937fe848b2cb0cc0836280d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs
new file mode 100644
index 0000000..807093e
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskCopyBuildinFiles_BBP : TaskCopyBuildinFiles, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var manifestContext = context.GetContextObject();
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
+ {
+ CopyBuildinFilesToStreaming(buildParametersContext, manifestContext.Manifest);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs.meta
new file mode 100644
index 0000000..537a68d
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCopyBuildinFiles_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 80c30fb9eb35a514daadefa4a2fb4f28
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs
new file mode 100644
index 0000000..32c46ea
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateManifest_BBP : TaskCreateManifest, IBuildTask
+ {
+ private TaskBuilding_BBP.BuildResultContext _buildResultContext = null;
+
+ void IBuildTask.Run(BuildContext context)
+ {
+ CreateManifestFile(context);
+ }
+
+ protected override string[] GetBundleDepends(BuildContext context, string bundleName)
+ {
+ if (_buildResultContext == null)
+ _buildResultContext = context.GetContextObject();
+
+ return _buildResultContext.UnityManifest.GetAllDependencies(bundleName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs.meta
new file mode 100644
index 0000000..89cb837
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateManifest_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: db8a306d84a7b284f9acc8925cfaf812
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs
new file mode 100644
index 0000000..530b1b7
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs
@@ -0,0 +1,53 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreatePackage_BBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild && buildMode != EBuildMode.DryRunBuild)
+ {
+ CreatePackageCatalog(buildParameters, buildMapContext);
+ }
+ }
+
+ ///
+ /// 拷贝补丁文件到补丁包目录
+ ///
+ private void CreatePackageCatalog(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
+ {
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ BuildLogger.Log($"Start making patch package: {packageOutputDirectory}");
+
+ // 拷贝UnityManifest序列化文件
+ {
+ string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}";
+ string destPath = $"{packageOutputDirectory}/{YooAssetSettings.OutputFolderName}";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝UnityManifest文本文件
+ {
+ string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}.manifest";
+ string destPath = $"{packageOutputDirectory}/{YooAssetSettings.OutputFolderName}.manifest";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝所有补丁文件
+ int progressValue = 0;
+ int fileTotalCount = buildMapContext.Collection.Count;
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ EditorTools.CopyFile(bundleInfo.PackageSourceFilePath, bundleInfo.PackageDestFilePath, true);
+ EditorTools.DisplayProgressBar("Copy patch file", ++progressValue, fileTotalCount);
+ }
+ EditorTools.ClearProgressBar();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs.meta
new file mode 100644
index 0000000..d667dae
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreatePackage_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 509e58fe0b061a54795f60209fbbbb5a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs
new file mode 100644
index 0000000..aa363ad
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateReport_BBP : TaskCreateReport, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var manifestContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild)
+ {
+ CreateReportFile(buildParameters, buildMapContext, manifestContext);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs.meta
new file mode 100644
index 0000000..e2e7c64
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskCreateReport_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cb66f3d5c56a85643a0e009d59079e54
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs
new file mode 100644
index 0000000..0248499
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskEncryption_BBP : TaskEncryption, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ EncryptingBundleFiles(buildParameters, buildMapContext);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs.meta
new file mode 100644
index 0000000..60bee27
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskEncryption_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6e871faedf2401c4c9225eb9815c5aa0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs
new file mode 100644
index 0000000..68a6cc0
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskGetBuildMap_BBP : TaskGetBuildMap, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = CreateBuildMap(buildParametersContext.Parameters);
+ context.SetContextObject(buildMapContext);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs.meta
new file mode 100644
index 0000000..9787488
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskGetBuildMap_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b621fbca3fe162448bda8c817daa101a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs
new file mode 100644
index 0000000..bcceb30
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskPrepare_BBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters;
+ var builtinBuildParameters = buildParameters as BuiltinBuildParameters;
+
+ // 检测基础构建参数
+ buildParametersContext.CheckBuildParameters();
+
+ // 检测Unity版本
+#if UNITY_2021_3_OR_NEWER
+ if (buildParameters.BuildMode != EBuildMode.SimulateBuild)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.RecommendScriptBuildPipeline, $"Starting with UnityEngine2021, recommend use script build pipeline (SBP) !");
+ BuildLogger.Warning(warning);
+ }
+#endif
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs.meta
new file mode 100644
index 0000000..3ee963d
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskPrepare_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6dc94501197179048b85b6e959c50e9c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs
new file mode 100644
index 0000000..5aaccfb
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs
@@ -0,0 +1,91 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskUpdateBundleInfo_BBP : TaskUpdateBundleInfo, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ UpdateBundleInfo(context);
+ }
+
+ protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var parameters = buildParametersContext.Parameters;
+ var buildMode = parameters.BuildMode;
+ if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
+ {
+ return "00000000000000000000000000000000"; //32位
+ }
+ else
+ {
+ var buildResult = context.GetContextObject();
+ var hash = buildResult.UnityManifest.GetAssetBundleHash(bundleInfo.BundleName);
+ if (hash.isValid)
+ {
+ return hash.ToString();
+ }
+ else
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleHash, $"Not found unity bundle hash : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ }
+ }
+ protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var parameters = buildParametersContext.Parameters;
+ var buildMode = parameters.BuildMode;
+ if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
+ {
+ return 0;
+ }
+ else
+ {
+ string filePath = bundleInfo.BuildOutputFilePath;
+ if (BuildPipeline.GetCRCForAssetBundle(filePath, out uint crc))
+ {
+ return crc;
+ }
+ else
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleCRC, $"Not found unity bundle crc : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ }
+ }
+ protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
+ return GetFilePathTempHash(filePath);
+ else
+ return HashUtility.FileMD5(filePath);
+ }
+ protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
+ return "00000000"; //8位
+ else
+ return HashUtility.FileCRC32(filePath);
+ }
+ protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
+ return GetBundleTempSize(bundleInfo);
+ else
+ return FileUtility.GetFileSize(filePath);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs.meta
new file mode 100644
index 0000000..5e4099f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskUpdateBundleInfo_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 26a84c5ae3c1a344883de3f85d48c952
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs
new file mode 100644
index 0000000..3203ccf
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskVerifyBuildResult_BBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
+
+ // 模拟构建模式下跳过验证
+ if (buildParameters.BuildMode == EBuildMode.SimulateBuild)
+ return;
+
+ // 验证构建结果
+ if (buildParameters.VerifyBuildingResult)
+ {
+ var buildResultContext = context.GetContextObject();
+ VerifyingBuildingResult(context, buildResultContext.UnityManifest);
+ }
+ }
+
+ ///
+ /// 验证构建结果
+ ///
+ private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ string[] unityCreateBundles = unityManifest.GetAllAssetBundles();
+
+ // 1. 过滤掉原生Bundle
+ string[] mapBundles = buildMapContext.Collection.Select(t => t.BundleName).ToArray();
+
+ // 2. 验证Bundle
+ List exceptBundleList1 = unityCreateBundles.Except(mapBundles).ToList();
+ if (exceptBundleList1.Count > 0)
+ {
+ foreach (var exceptBundle in exceptBundleList1)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
+ BuildLogger.Warning(warning);
+ }
+
+ string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
+ throw new Exception(exception);
+ }
+
+ // 3. 验证Bundle
+ List exceptBundleList2 = mapBundles.Except(unityCreateBundles).ToList();
+ if (exceptBundleList2.Count > 0)
+ {
+ foreach (var exceptBundle in exceptBundleList2)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
+ BuildLogger.Warning(warning);
+ }
+
+ string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
+ throw new Exception(exception);
+ }
+
+ BuildLogger.Log("Build results verify success!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs.meta
new file mode 100644
index 0000000..14d6cd1
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuildTasks/TaskVerifyBuildResult_BBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b883ac0c3c25e8143847a9326e2961cf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs
new file mode 100644
index 0000000..da4c538
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class BuiltinBuildParameters : BuildParameters
+ {
+ ///
+ /// 压缩选项
+ ///
+ public ECompressOption CompressOption = ECompressOption.Uncompressed;
+
+ ///
+ /// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
+ ///
+ public bool DisableWriteTypeTree = false;
+
+ ///
+ /// 忽略类型树变化
+ ///
+ public bool IgnoreTypeTreeChanges = true;
+
+
+ ///
+ /// 获取内置构建管线的构建选项
+ ///
+ public BuildAssetBundleOptions GetBundleBuildOptions()
+ {
+ // For the new build system, unity always need BuildAssetBundleOptions.CollectDependencies and BuildAssetBundleOptions.DeterministicAssetBundle
+ // 除非设置ForceRebuildAssetBundle标记,否则会进行增量打包
+
+ BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
+ opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
+
+ if (BuildMode == EBuildMode.DryRunBuild)
+ {
+ opt |= BuildAssetBundleOptions.DryRunBuild;
+ return opt;
+ }
+
+ if (CompressOption == ECompressOption.Uncompressed)
+ opt |= BuildAssetBundleOptions.UncompressedAssetBundle;
+ else if (CompressOption == ECompressOption.LZ4)
+ opt |= BuildAssetBundleOptions.ChunkBasedCompression;
+
+ if (BuildMode == EBuildMode.ForceRebuild)
+ opt |= BuildAssetBundleOptions.ForceRebuildAssetBundle; //Force rebuild the asset bundles
+ if (DisableWriteTypeTree)
+ opt |= BuildAssetBundleOptions.DisableWriteTypeTree; //Do not include type information within the asset bundle (don't write type tree).
+ if (IgnoreTypeTreeChanges)
+ opt |= BuildAssetBundleOptions.IgnoreTypeTreeChanges; //Ignore the type tree changes when doing the incremental build check.
+
+ opt |= BuildAssetBundleOptions.DisableLoadAssetByFileName; //Disables Asset Bundle LoadAsset by file name.
+ opt |= BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension; //Disables Asset Bundle LoadAsset by file name with extension.
+
+ return opt;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs.meta
new file mode 100644
index 0000000..4999edf
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildParameters.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cd05d8038cf42e54e974483bb5da4198
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs
new file mode 100644
index 0000000..2ac4058
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class BuiltinBuildPipeline : IBuildPipeline
+ {
+ public BuildResult Run(BuildParameters buildParameters, bool enableLog)
+ {
+ AssetBundleBuilder builder = new AssetBundleBuilder();
+ return builder.Run(buildParameters, GetDefaultBuildPipeline(), enableLog);
+ }
+
+ ///
+ /// 获取默认的构建流程
+ ///
+ private List GetDefaultBuildPipeline()
+ {
+ List pipeline = new List
+ {
+ new TaskPrepare_BBP(),
+ new TaskGetBuildMap_BBP(),
+ new TaskBuilding_BBP(),
+ new TaskVerifyBuildResult_BBP(),
+ new TaskEncryption_BBP(),
+ new TaskUpdateBundleInfo_BBP(),
+ new TaskCreateManifest_BBP(),
+ new TaskCreateReport_BBP(),
+ new TaskCreatePackage_BBP(),
+ new TaskCopyBuildinFiles_BBP(),
+ };
+ return pipeline;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs.meta
new file mode 100644
index 0000000..324f03a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/BuiltinBuildPipeline/BuiltinBuildPipeline.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 62d7756143e561843800bc521b5e090f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline.meta
new file mode 100644
index 0000000..4f14777
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8a5f30f9c58f36946b2028bddce08c9c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks.meta
new file mode 100644
index 0000000..7b83789
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 141f7d1ebdf7cc147801aa711e29ac17
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs
new file mode 100644
index 0000000..cacb1df
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskBuilding_RFBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ CopyRawBundle(buildMapContext, buildParametersContext);
+ }
+ }
+
+ ///
+ /// 拷贝原生文件
+ ///
+ private void CopyRawBundle(BuildMapContext buildMapContext, BuildParametersContext buildParametersContext)
+ {
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ string dest = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
+ foreach (var buildAsset in bundleInfo.MainAssets)
+ {
+ EditorTools.CopyFile(buildAsset.AssetInfo.AssetPath, dest, true);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs.meta
new file mode 100644
index 0000000..a803fb3
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskBuilding_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3625d4b8b5b79324ebf7ec19a87677e7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs
new file mode 100644
index 0000000..4b9148f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskCopyBuildinFiles_RFBP : TaskCopyBuildinFiles, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters;
+ var manifestContext = context.GetContextObject();
+
+ if (buildParameters.BuildMode != EBuildMode.SimulateBuild)
+ {
+ if (buildParameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
+ {
+ CopyBuildinFilesToStreaming(buildParametersContext, manifestContext.Manifest);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs.meta
new file mode 100644
index 0000000..697821a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCopyBuildinFiles_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bf10a5495e90b844b8aca1eadf7ed8f7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs
new file mode 100644
index 0000000..4a7778a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateManifest_RFBP : TaskCreateManifest, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ CreateManifestFile(context);
+ }
+
+ protected override string[] GetBundleDepends(BuildContext context, string bundleName)
+ {
+ return new string[] { };
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs.meta
new file mode 100644
index 0000000..1daf9d2
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateManifest_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 86bdc7d5ae31fdd409f9dc68d73e2600
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs
new file mode 100644
index 0000000..f8a2a3b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs
@@ -0,0 +1,38 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreatePackage_RFBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild)
+ {
+ CreatePackageCatalog(buildParameters, buildMapContext);
+ }
+ }
+
+ ///
+ /// 拷贝补丁文件到补丁包目录
+ ///
+ private void CreatePackageCatalog(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
+ {
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ BuildLogger.Log($"Start making patch package: {packageOutputDirectory}");
+
+ // 拷贝所有补丁文件
+ int progressValue = 0;
+ int fileTotalCount = buildMapContext.Collection.Count;
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ EditorTools.CopyFile(bundleInfo.PackageSourceFilePath, bundleInfo.PackageDestFilePath, true);
+ EditorTools.DisplayProgressBar("Copy patch file", ++progressValue, fileTotalCount);
+ }
+ EditorTools.ClearProgressBar();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs.meta
new file mode 100644
index 0000000..1bb29cc
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreatePackage_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a6d813044f843b944b4ec3d6f562c7e2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs
new file mode 100644
index 0000000..83458c9
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateReport_RFBP : TaskCreateReport, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var manifestContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild)
+ {
+ CreateReportFile(buildParameters, buildMapContext, manifestContext);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs.meta
new file mode 100644
index 0000000..04e549c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskCreateReport_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 55595ba60c30a634d8921cfc6524e201
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs
new file mode 100644
index 0000000..88f99be
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs
@@ -0,0 +1,38 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskGetBuildMap_RFBP : TaskGetBuildMap, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = CreateBuildMap(buildParametersContext.Parameters);
+ context.SetContextObject(buildMapContext);
+
+ // 检测构建结果
+ CheckBuildMapContent(buildMapContext);
+ }
+
+ ///
+ /// 检测资源构建上下文
+ ///
+ private void CheckBuildMapContent(BuildMapContext buildMapContext)
+ {
+ // 注意:原生文件资源包只能包含一个原生文件
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ if (bundleInfo.MainAssets.Count != 1)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotSupportMultipleRawAsset, $"The bundle does not support multiple raw asset : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs.meta
new file mode 100644
index 0000000..091c0e9
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskGetBuildMap_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a8bdb5b4ee29e5b48a88689c6519b830
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs
new file mode 100644
index 0000000..6c836a5
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs
@@ -0,0 +1,39 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskPrepare_RFBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters;
+
+ // 检测基础构建参数
+ buildParametersContext.CheckBuildParameters();
+
+ // 检测不被支持的参数
+ if (buildParameters.EnableSharePackRule)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineNotSupportSharePackRule, $"{nameof(EBuildPipeline.RawFileBuildPipeline)} not support share pack rule !");
+ throw new Exception(message);
+ }
+
+ // 检测不被支持的构建模式
+ if (buildParameters.BuildMode == EBuildMode.DryRunBuild)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineNotSupportBuildMode, $"{nameof(EBuildPipeline.RawFileBuildPipeline)} not support {nameof(EBuildMode.DryRunBuild)} build mode !");
+ throw new Exception(message);
+ }
+ if (buildParameters.BuildMode == EBuildMode.IncrementalBuild)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineNotSupportBuildMode, $"{nameof(EBuildPipeline.RawFileBuildPipeline)} not support {nameof(EBuildMode.IncrementalBuild)} build mode !");
+ throw new Exception(message);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs.meta
new file mode 100644
index 0000000..3be82c1
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskPrepare_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 97204fd262bb58449a87e517318905c3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs
new file mode 100644
index 0000000..ffc8571
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskUpdateBundleInfo_RFBP : TaskUpdateBundleInfo, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ UpdateBundleInfo(context);
+ }
+
+ protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var parameters = buildParametersContext.Parameters;
+ var buildMode = parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ {
+ return "00000000000000000000000000000000"; //32位
+ }
+ else
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ return HashUtility.FileMD5(filePath);
+ }
+ }
+ protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ return 0;
+ }
+ protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return GetFilePathTempHash(filePath);
+ else
+ return HashUtility.FileMD5(filePath);
+ }
+ protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return "00000000"; //8位
+ else
+ return HashUtility.FileCRC32(filePath);
+ }
+ protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return GetBundleTempSize(bundleInfo);
+ else
+ return FileUtility.GetFileSize(filePath);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs.meta
new file mode 100644
index 0000000..5dc4f47
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/BuildTasks/TaskUpdateBundleInfo_RFBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b2c8ae6a3e6ca3b4bba4e1495ea297d4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs
new file mode 100644
index 0000000..eedb8d5
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs
@@ -0,0 +1,10 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class RawFileBuildParameters : BuildParameters
+ {
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs.meta
new file mode 100644
index 0000000..7703739
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildParameters.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d5ba9a5c89be56147a651be73b1d8a30
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs
new file mode 100644
index 0000000..dd784ad
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Linq;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class RawFileBuildPipeline : IBuildPipeline
+ {
+ public BuildResult Run(BuildParameters buildParameters, bool enableLog)
+ {
+ AssetBundleBuilder builder = new AssetBundleBuilder();
+ return builder.Run(buildParameters, GetDefaultBuildPipeline(), enableLog);
+ }
+
+ ///
+ /// 获取默认的构建流程
+ ///
+ private List GetDefaultBuildPipeline()
+ {
+ List pipeline = new()
+ {
+ new TaskPrepare_RFBP(),
+ new TaskGetBuildMap_RFBP(),
+ new TaskBuilding_RFBP(),
+ new TaskUpdateBundleInfo_RFBP(),
+ new TaskCreateManifest_RFBP(),
+ new TaskCreateReport_RFBP(),
+ new TaskCreatePackage_RFBP(),
+ new TaskCopyBuildinFiles_RFBP(),
+ };
+ return pipeline;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs.meta
new file mode 100644
index 0000000..93f10a2
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/RawFileBuildPipeline/RawFileBuildPipeline.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ee1731ae83e2f0045bab58773be95743
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline.meta
new file mode 100644
index 0000000..871f32f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c8b9d8597bfdc994e9ef52f319cc96ec
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks.meta
new file mode 100644
index 0000000..26ca0ef
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 64c9242d4708b1f47b1469897bbfe127
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs
new file mode 100644
index 0000000..03cbd54
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor.Build.Pipeline;
+using UnityEditor.Build.Pipeline.Interfaces;
+using UnityEditor.Build.Pipeline.Tasks;
+
+namespace YooAsset.Editor
+{
+ public class TaskBuilding_SBP : IBuildTask
+ {
+ public class BuildResultContext : IContextObject
+ {
+ public IBundleBuildResults Results;
+ }
+
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
+
+ // 模拟构建模式下跳过引擎构建
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return;
+
+ // 构建内容
+ var buildContent = new BundleBuildContent(buildMapContext.GetPipelineBuilds());
+
+ // 开始构建
+ IBundleBuildResults buildResults;
+ var buildParameters = scriptableBuildParameters.GetBundleBuildParameters();
+ var taskList = SBPBuildTasks.Create(buildMapContext.Command.ShadersBundleName);
+ ReturnCode exitCode = ContentPipeline.BuildAssetBundles(buildParameters, buildContent, out buildResults, taskList);
+ if (exitCode < 0)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, $"UnityEngine build failed ! ReturnCode : {exitCode}");
+ throw new Exception(message);
+ }
+
+ // 创建着色器信息
+ // 说明:解决因为着色器资源包导致验证失败。
+ // 例如:当项目里没有着色器,如果有依赖内置着色器就会验证失败。
+ string shadersBundleName = buildMapContext.Command.ShadersBundleName;
+ if (buildResults.BundleInfos.ContainsKey(shadersBundleName))
+ {
+ buildMapContext.CreateShadersBundleInfo(shadersBundleName);
+ }
+
+ BuildLogger.Log("UnityEngine build success!");
+ BuildResultContext buildResultContext = new BuildResultContext();
+ buildResultContext.Results = buildResults;
+ context.SetContextObject(buildResultContext);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs.meta
new file mode 100644
index 0000000..91a0eb9
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskBuilding_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 255306458772c8b4eb94ca288dfc77ac
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs
new file mode 100644
index 0000000..c830064
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class TaskCopyBuildinFiles_SBP : TaskCopyBuildinFiles, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var manifestContext = context.GetContextObject();
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
+ {
+ CopyBuildinFilesToStreaming(buildParametersContext, manifestContext.Manifest);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs.meta
new file mode 100644
index 0000000..ef55b62
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCopyBuildinFiles_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 67f8cc89ad41abe42aa1eed9a3d41f20
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs
new file mode 100644
index 0000000..df244ec
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor.Build.Pipeline;
+using UnityEditor.Build.Pipeline.Interfaces;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateManifest_SBP : TaskCreateManifest, IBuildTask
+ {
+ private TaskBuilding_SBP.BuildResultContext _buildResultContext = null;
+
+ void IBuildTask.Run(BuildContext context)
+ {
+ CreateManifestFile(context);
+ }
+
+ protected override string[] GetBundleDepends(BuildContext context, string bundleName)
+ {
+ if (_buildResultContext == null)
+ _buildResultContext = context.GetContextObject();
+
+ if (_buildResultContext.Results.BundleInfos.ContainsKey(bundleName) == false)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleInBuildResult, $"Not found bundle in engine build result : {bundleName}");
+ throw new Exception(message);
+ }
+ return _buildResultContext.Results.BundleInfos[bundleName].Dependencies;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs.meta
new file mode 100644
index 0000000..9b33572
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateManifest_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: adfbea99cce4707409469a37c7e5da31
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs
new file mode 100644
index 0000000..5fa6569
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs
@@ -0,0 +1,55 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreatePackage_SBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild)
+ {
+ CreatePackageCatalog(buildParameters, buildMapContext);
+ }
+ }
+
+ ///
+ /// 拷贝补丁文件到补丁包目录
+ ///
+ private void CreatePackageCatalog(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
+ {
+ var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
+ string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
+ string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
+ BuildLogger.Log($"Start making patch package: {packageOutputDirectory}");
+
+ // 拷贝构建日志
+ {
+ string sourcePath = $"{pipelineOutputDirectory}/buildlogtep.json";
+ string destPath = $"{packageOutputDirectory}/buildlogtep.json";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝代码防裁剪配置
+ if (scriptableBuildParameters.WriteLinkXML)
+ {
+ string sourcePath = $"{pipelineOutputDirectory}/link.xml";
+ string destPath = $"{packageOutputDirectory}/link.xml";
+ EditorTools.CopyFile(sourcePath, destPath, true);
+ }
+
+ // 拷贝所有补丁文件
+ int progressValue = 0;
+ int fileTotalCount = buildMapContext.Collection.Count;
+ foreach (var bundleInfo in buildMapContext.Collection)
+ {
+ EditorTools.CopyFile(bundleInfo.PackageSourceFilePath, bundleInfo.PackageDestFilePath, true);
+ EditorTools.DisplayProgressBar("Copy patch file", ++progressValue, fileTotalCount);
+ }
+ EditorTools.ClearProgressBar();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs.meta
new file mode 100644
index 0000000..3ed2a85
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreatePackage_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c798c7056a23c8840af89492d30cb89c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs
new file mode 100644
index 0000000..5c7c8be
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskCreateReport_SBP : TaskCreateReport, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ var manifestContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode != EBuildMode.SimulateBuild)
+ {
+ CreateReportFile(buildParameters, buildMapContext, manifestContext);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs.meta
new file mode 100644
index 0000000..5e1c710
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskCreateReport_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 11893a8199d4d8549b76a16c740d507a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs
new file mode 100644
index 0000000..8b1ffae
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class TaskEncryption_SBP : TaskEncryption, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+
+ var buildMode = buildParameters.Parameters.BuildMode;
+ if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
+ {
+ EncryptingBundleFiles(buildParameters, buildMapContext);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs.meta
new file mode 100644
index 0000000..18f96b6
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskEncryption_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ff8ba0dd63fc3304c8f20680733a74e0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs
new file mode 100644
index 0000000..938f607
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskGetBuildMap_SBP : TaskGetBuildMap, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildMapContext = CreateBuildMap(buildParametersContext.Parameters);
+ context.SetContextObject(buildMapContext);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs.meta
new file mode 100644
index 0000000..37bf02c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskGetBuildMap_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cc3a7680622c5254f80b9541196091c3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs
new file mode 100644
index 0000000..0fbf321
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskPrepare_SBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters;
+
+ // 检测基础构建参数
+ buildParametersContext.CheckBuildParameters();
+
+ // 检测不被支持的构建模式
+ if (buildParameters.BuildMode == EBuildMode.DryRunBuild)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineNotSupportBuildMode, $"{nameof(EBuildPipeline.ScriptableBuildPipeline)} not support {nameof(EBuildMode.DryRunBuild)} build mode !");
+ throw new Exception(message);
+ }
+ if (buildParameters.BuildMode == EBuildMode.ForceRebuild)
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineNotSupportBuildMode, $"{nameof(EBuildPipeline.ScriptableBuildPipeline)} not support {nameof(EBuildMode.ForceRebuild)} build mode !");
+ throw new Exception(message);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs.meta
new file mode 100644
index 0000000..a89d526
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskPrepare_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 698615f2a9590ef488a62419111d1e3d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs
new file mode 100644
index 0000000..4cc4812
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs
@@ -0,0 +1,91 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class TaskUpdateBundleInfo_SBP : TaskUpdateBundleInfo, IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ UpdateBundleInfo(context);
+ }
+
+ protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var parameters = buildParametersContext.Parameters;
+ var buildMode = parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ {
+ return "00000000000000000000000000000000"; //32位
+ }
+ else
+ {
+ // 注意:当资源包的依赖列表发生变化的时候,ContentHash也会发生变化!
+ var buildResult = context.GetContextObject();
+ if (buildResult.Results.BundleInfos.TryGetValue(bundleInfo.BundleName, out var value))
+ {
+ return value.Hash.ToString();
+ }
+ else
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleHash, $"Not found unity bundle hash : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ }
+ }
+ protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var parameters = buildParametersContext.Parameters;
+ var buildMode = parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ {
+ return 0;
+ }
+ else
+ {
+ var buildResult = context.GetContextObject();
+ if (buildResult.Results.BundleInfos.TryGetValue(bundleInfo.BundleName, out var value))
+ {
+ return value.Crc;
+ }
+ else
+ {
+ string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleCRC, $"Not found unity bundle crc : {bundleInfo.BundleName}");
+ throw new Exception(message);
+ }
+ }
+ }
+ protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return GetFilePathTempHash(filePath);
+ else
+ return HashUtility.FileMD5(filePath);
+ }
+ protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return "00000000"; //8位
+ else
+ return HashUtility.FileCRC32(filePath);
+ }
+ protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
+ {
+ string filePath = bundleInfo.PackageSourceFilePath;
+ var buildMode = buildParametersContext.Parameters.BuildMode;
+ if (buildMode == EBuildMode.SimulateBuild)
+ return GetBundleTempSize(bundleInfo);
+ else
+ return FileUtility.GetFileSize(filePath);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs.meta
new file mode 100644
index 0000000..8bf56e8
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskUpdateBundleInfo_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c53b8e8dd0618e344931ad9ac4ad0656
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs
new file mode 100644
index 0000000..db6630b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Linq;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using UnityEditor.Build.Pipeline.Interfaces;
+
+namespace YooAsset.Editor
+{
+ public class TaskVerifyBuildResult_SBP : IBuildTask
+ {
+ void IBuildTask.Run(BuildContext context)
+ {
+ var buildParametersContext = context.GetContextObject();
+ var buildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
+
+ // 模拟构建模式下跳过验证
+ if (buildParameters.BuildMode == EBuildMode.SimulateBuild)
+ return;
+
+ // 验证构建结果
+ if (buildParameters.VerifyBuildingResult)
+ {
+ var buildResultContext = context.GetContextObject();
+ VerifyingBuildingResult(context, buildResultContext.Results);
+ }
+ }
+
+ ///
+ /// 验证构建结果
+ ///
+ private void VerifyingBuildingResult(BuildContext context, IBundleBuildResults buildResults)
+ {
+ var buildParameters = context.GetContextObject();
+ var buildMapContext = context.GetContextObject();
+ List unityCreateBundles = buildResults.BundleInfos.Keys.ToList();
+
+ // 1. 过滤掉原生Bundle
+ List expectBundles = buildMapContext.Collection.Select(t => t.BundleName).ToList();
+
+ // 2. 验证Bundle
+ List exceptBundleList1 = unityCreateBundles.Except(expectBundles).ToList();
+ if (exceptBundleList1.Count > 0)
+ {
+ foreach (var exceptBundle in exceptBundleList1)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
+ BuildLogger.Warning(warning);
+ }
+
+ string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
+ throw new Exception(exception);
+ }
+
+ // 3. 验证Bundle
+ List exceptBundleList2 = expectBundles.Except(unityCreateBundles).ToList();
+ if (exceptBundleList2.Count > 0)
+ {
+ foreach (var exceptBundle in exceptBundleList2)
+ {
+ string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
+ BuildLogger.Warning(warning);
+ }
+
+ string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
+ throw new Exception(exception);
+ }
+
+ BuildLogger.Log("Build results verify success!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs.meta
new file mode 100644
index 0000000..f74469c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/BuildTasks/TaskVerifyBuildResult_SBP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 16aa7c2c37209a043b4f33d7854047c6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs
new file mode 100644
index 0000000..7ba0d05
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor.Build.Pipeline;
+using UnityEditor.Build.Pipeline.Interfaces;
+
+namespace UnityEditor.Build.Pipeline.Tasks
+{
+ public static class SBPBuildTasks
+ {
+ public static IList Create(string builtInShaderBundleName)
+ {
+ var buildTasks = new List();
+
+ // Setup
+ buildTasks.Add(new SwitchToBuildPlatform());
+ buildTasks.Add(new RebuildSpriteAtlasCache());
+
+ // Player Scripts
+ buildTasks.Add(new BuildPlayerScripts());
+ buildTasks.Add(new PostScriptsCallback());
+
+ // Dependency
+ buildTasks.Add(new CalculateSceneDependencyData());
+#if UNITY_2019_3_OR_NEWER
+ buildTasks.Add(new CalculateCustomDependencyData());
+#endif
+ buildTasks.Add(new CalculateAssetDependencyData());
+ buildTasks.Add(new StripUnusedSpriteSources());
+ buildTasks.Add(new CreateBuiltInShadersBundle(builtInShaderBundleName));
+ buildTasks.Add(new PostDependencyCallback());
+
+ // Packing
+ buildTasks.Add(new GenerateBundlePacking());
+ buildTasks.Add(new UpdateBundleObjectLayout());
+ buildTasks.Add(new GenerateBundleCommands());
+ buildTasks.Add(new GenerateSubAssetPathMaps());
+ buildTasks.Add(new GenerateBundleMaps());
+ buildTasks.Add(new PostPackingCallback());
+
+ // Writing
+ buildTasks.Add(new WriteSerializedFiles());
+ buildTasks.Add(new ArchiveAndCompressBundles());
+ buildTasks.Add(new AppendBundleHash());
+ buildTasks.Add(new GenerateLinkXml());
+ buildTasks.Add(new PostWritingCallback());
+
+ return buildTasks;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs.meta
new file mode 100644
index 0000000..2767c0b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/SBPBuildTasks.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f38422f6a64300243af6b4fbf84644ba
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs
new file mode 100644
index 0000000..7f3e1a6
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEditor.Build.Pipeline;
+using UnityEditor.Build.Pipeline.Interfaces;
+
+namespace YooAsset.Editor
+{
+ public class ScriptableBuildParameters : BuildParameters
+ {
+ ///
+ /// 压缩选项
+ ///
+ public ECompressOption CompressOption = ECompressOption.Uncompressed;
+
+ ///
+ /// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
+ ///
+ public bool DisableWriteTypeTree = false;
+
+ ///
+ /// 忽略类型树变化
+ ///
+ public bool IgnoreTypeTreeChanges = true;
+
+
+ ///
+ /// 生成代码防裁剪配置
+ ///
+ public bool WriteLinkXML = true;
+
+ ///
+ /// 缓存服务器地址
+ ///
+ public string CacheServerHost;
+
+ ///
+ /// 缓存服务器端口
+ ///
+ public int CacheServerPort;
+
+
+ ///
+ /// 获取可编程构建管线的构建参数
+ ///
+ public BundleBuildParameters GetBundleBuildParameters()
+ {
+ var targetGroup = UnityEditor.BuildPipeline.GetBuildTargetGroup(BuildTarget);
+ var pipelineOutputDirectory = GetPipelineOutputDirectory();
+ var buildParams = new BundleBuildParameters(BuildTarget, targetGroup, pipelineOutputDirectory);
+
+ if (CompressOption == ECompressOption.Uncompressed)
+ buildParams.BundleCompression = UnityEngine.BuildCompression.Uncompressed;
+ else if (CompressOption == ECompressOption.LZMA)
+ buildParams.BundleCompression = UnityEngine.BuildCompression.LZMA;
+ else if (CompressOption == ECompressOption.LZ4)
+ buildParams.BundleCompression = UnityEngine.BuildCompression.LZ4;
+ else
+ throw new System.NotImplementedException(CompressOption.ToString());
+
+ if (DisableWriteTypeTree)
+ buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;
+
+ buildParams.UseCache = true;
+ buildParams.CacheServerHost = CacheServerHost;
+ buildParams.CacheServerPort = CacheServerPort;
+ buildParams.WriteLinkXML = WriteLinkXML;
+
+ return buildParams;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs.meta
new file mode 100644
index 0000000..281869c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildParameters.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 83ca8a0609deaf04d9d1f1f0d396efa9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs
new file mode 100644
index 0000000..db62db6
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class ScriptableBuildPipeline : IBuildPipeline
+ {
+ public BuildResult Run(BuildParameters buildParameters, bool enableLog)
+ {
+ AssetBundleBuilder builder = new AssetBundleBuilder();
+ return builder.Run(buildParameters, GetDefaultBuildPipeline(), enableLog);
+ }
+
+ ///
+ /// 获取默认的构建流程
+ ///
+ private List GetDefaultBuildPipeline()
+ {
+ List pipeline = new List
+ {
+ new TaskPrepare_SBP(),
+ new TaskGetBuildMap_SBP(),
+ new TaskBuilding_SBP(),
+ new TaskVerifyBuildResult_SBP(),
+ new TaskEncryption_SBP(),
+ new TaskUpdateBundleInfo_SBP(),
+ new TaskCreateManifest_SBP(),
+ new TaskCreateReport_SBP(),
+ new TaskCreatePackage_SBP(),
+ new TaskCopyBuildinFiles_SBP(),
+ };
+ return pipeline;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs.meta b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs.meta
new file mode 100644
index 0000000..6641303
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildPipeline/ScriptableBuildPipeline/ScriptableBuildPipeline.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2e2dcea2c826dc94d8b439f724b25d57
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem.meta b/Editor/AssetBundleBuilder/BuildSystem.meta
new file mode 100644
index 0000000..59ef26f
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2875232ad7f87c148b752d432f3a54f2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs b/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs
new file mode 100644
index 0000000..668415a
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace YooAsset.Editor
+{
+ public class BuildContext
+ {
+ private readonly Dictionary _contextObjects = new Dictionary();
+
+ ///
+ /// 清空所有情景对象
+ ///
+ public void ClearAllContext()
+ {
+ _contextObjects.Clear();
+ }
+
+ ///
+ /// 设置情景对象
+ ///
+ public void SetContextObject(IContextObject contextObject)
+ {
+ if (contextObject == null)
+ throw new ArgumentNullException("contextObject");
+
+ var type = contextObject.GetType();
+ if (_contextObjects.ContainsKey(type))
+ throw new Exception($"Context object {type} is already existed.");
+
+ _contextObjects.Add(type, contextObject);
+ }
+
+ ///
+ /// 获取情景对象
+ ///
+ public T GetContextObject() where T : IContextObject
+ {
+ var type = typeof(T);
+ if (_contextObjects.TryGetValue(type, out IContextObject contextObject))
+ {
+ return (T)contextObject;
+ }
+ else
+ {
+ throw new Exception($"Not found context object : {type}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs.meta
new file mode 100644
index 0000000..d2fa01b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildContext.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6a232601f99c4634ea17fca4979f80ab
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs b/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs
new file mode 100644
index 0000000..abac194
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs
@@ -0,0 +1,38 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ internal static class BuildLogger
+ {
+ private static bool _enableLog = true;
+
+ public static void InitLogger(bool enableLog)
+ {
+ _enableLog = enableLog;
+ }
+
+ public static void Log(string message)
+ {
+ if (_enableLog)
+ {
+ Debug.Log(message);
+ }
+ }
+ public static void Warning(string message)
+ {
+ Debug.LogWarning(message);
+ }
+ public static void Error(string message)
+ {
+ Debug.LogError(message);
+ }
+
+ public static string GetErrorMessage(ErrorCode code, string message)
+ {
+ return $"[ErrorCode{(int)code}] {message}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs.meta
new file mode 100644
index 0000000..8fad97d
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildLogger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2bc82466a51f50141975e4424095aa09
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs b/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs
new file mode 100644
index 0000000..fe4e251
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs
@@ -0,0 +1,29 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 构建结果
+ ///
+ public class BuildResult
+ {
+ ///
+ /// 构建是否成功
+ ///
+ public bool Success;
+
+ ///
+ /// 构建失败的任务
+ ///
+ public string FailedTask;
+
+ ///
+ /// 构建失败的信息
+ ///
+ public string ErrorInfo;
+
+ ///
+ /// 输出的补丁包目录
+ ///
+ public string OutputPackageDirectory;
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs.meta
new file mode 100644
index 0000000..a8ebe2b
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildResult.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e0855c4b5eaa26942bd7ad177fe3c288
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs b/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs
new file mode 100644
index 0000000..314c178
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Diagnostics;
+using PhxhSDK.AOT;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class BuildRunner
+ {
+ private static Stopwatch _buildWatch;
+
+ ///
+ /// 总耗时
+ ///
+ public static int TotalSeconds = 0;
+
+ ///
+ /// 执行构建流程
+ ///
+ /// 如果成功返回TRUE,否则返回FALSE
+ public static BuildResult Run(List pipeline, BuildContext context)
+ {
+ if (pipeline == null)
+ throw new ArgumentNullException("pipeline");
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ BuildResult buildResult = new BuildResult();
+ buildResult.Success = true;
+ TotalSeconds = 0;
+ YooAssetBuildStatus.isInBuild = true;
+
+ for (int i = 0; i < pipeline.Count; i++)
+ {
+ IBuildTask task = pipeline[i];
+ try
+ {
+ _buildWatch = Stopwatch.StartNew();
+ string taskName = task.GetType().Name.Split('_')[0];
+ BuildLogger.Log($"--------------------------------------------->{taskName}<--------------------------------------------");
+ task.Run(context);
+ _buildWatch.Stop();
+
+ // 统计耗时
+ int seconds = GetBuildSeconds();
+ TotalSeconds += seconds;
+ BuildLogger.Log($"{taskName} It takes {seconds} seconds in total");
+ }
+ catch (Exception e)
+ {
+ EditorTools.ClearProgressBar();
+ buildResult.FailedTask = task.GetType().Name;
+ buildResult.ErrorInfo = e.ToString();
+ buildResult.Success = false;
+ break;
+ }
+ }
+ YooAssetBuildStatus.isInBuild = false;
+ // 返回运行结果
+ BuildLogger.Log($"Total build process time: {TotalSeconds} seconds");
+ return buildResult;
+ }
+
+ private static int GetBuildSeconds()
+ {
+ float seconds = _buildWatch.ElapsedMilliseconds / 1000f;
+ return (int)seconds;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs.meta
new file mode 100644
index 0000000..ad8b244
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/BuildRunner.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 79014124da678684388454d6ea892722
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs b/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs
new file mode 100644
index 0000000..2fb0bdb
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs
@@ -0,0 +1,43 @@
+
+namespace YooAsset.Editor
+{
+ internal enum ErrorCode
+ {
+ // TaskPrepare
+ ThePipelineIsBuiding = 100,
+ FoundUnsavedScene = 101,
+ NoBuildTarget = 110,
+ PackageNameIsNullOrEmpty = 111,
+ PackageVersionIsNullOrEmpty = 112,
+ BuildOutputRootIsNullOrEmpty = 113,
+ BuildinFileRootIsNullOrEmpty = 114,
+ PackageOutputDirectoryExists = 115,
+ RecommendScriptBuildPipeline = 130,
+ BuildPipelineNotSupportBuildMode = 140,
+ BuildPipelineNotSupportSharePackRule = 141,
+
+ // TaskGetBuildMap
+ RemoveInvalidTags = 200,
+ FoundUndependedAsset = 201,
+ PackAssetListIsEmpty = 202,
+ NotSupportMultipleRawAsset = 210,
+
+ // TaskBuilding
+ UnityEngineBuildFailed = 300,
+ UnityEngineBuildFatal = 301,
+
+ // TaskUpdateBundleInfo
+ CharactersOverTheLimit = 400,
+ NotFoundUnityBundleHash = 401,
+ NotFoundUnityBundleCRC = 402,
+ BundleTempSizeIsZero = 403,
+
+ // TaskVerifyBuildResult
+ UnintendedBuildBundle = 500,
+ UnintendedBuildResult = 501,
+
+ // TaskCreateManifest
+ NotFoundUnityBundleInBuildResult = 600,
+ FoundStrayBundle = 601,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs.meta
new file mode 100644
index 0000000..a6cc606
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/ErrorCode.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c3a10fd19801c0c428bac53081a96517
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs b/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs
new file mode 100644
index 0000000..7158143
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs
@@ -0,0 +1,8 @@
+
+namespace YooAsset.Editor
+{
+ public interface IBuildTask
+ {
+ void Run(BuildContext context);
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs.meta
new file mode 100644
index 0000000..f6b7e53
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/IBuildTask.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8888657c45e12c646a8349bac6bf0326
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs b/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs
new file mode 100644
index 0000000..2a5a12c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs
@@ -0,0 +1,7 @@
+
+namespace YooAsset.Editor
+{
+ public interface IContextObject
+ {
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs.meta b/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs.meta
new file mode 100644
index 0000000..c51328c
--- /dev/null
+++ b/Editor/AssetBundleBuilder/BuildSystem/IContextObject.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 151a4acd5ad1c2046be20e080f9bdad4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/DefaultEncryption.cs b/Editor/AssetBundleBuilder/DefaultEncryption.cs
new file mode 100644
index 0000000..8cdb2b1
--- /dev/null
+++ b/Editor/AssetBundleBuilder/DefaultEncryption.cs
@@ -0,0 +1,11 @@
+
+namespace YooAsset.Editor
+{
+ public class EncryptionNone : IEncryptionServices
+ {
+ public EncryptResult Encrypt(EncryptFileInfo fileInfo)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/DefaultEncryption.cs.meta b/Editor/AssetBundleBuilder/DefaultEncryption.cs.meta
new file mode 100644
index 0000000..3c666d3
--- /dev/null
+++ b/Editor/AssetBundleBuilder/DefaultEncryption.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 46b8b200b841799498896403d9d427c2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/EBuildMode.cs b/Editor/AssetBundleBuilder/EBuildMode.cs
new file mode 100644
index 0000000..e939327
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildMode.cs
@@ -0,0 +1,29 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 资源包流水线的构建模式
+ ///
+ public enum EBuildMode
+ {
+ ///
+ /// 强制重建模式
+ ///
+ ForceRebuild,
+
+ ///
+ /// 增量构建模式
+ ///
+ IncrementalBuild,
+
+ ///
+ /// 演练构建模式
+ ///
+ DryRunBuild,
+
+ ///
+ /// 模拟构建模式
+ ///
+ SimulateBuild,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/EBuildMode.cs.meta b/Editor/AssetBundleBuilder/EBuildMode.cs.meta
new file mode 100644
index 0000000..36454fc
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildMode.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0b6f2523a865e454d8fa3f48a2852d5a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/EBuildPipeline.cs b/Editor/AssetBundleBuilder/EBuildPipeline.cs
new file mode 100644
index 0000000..85f33c0
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildPipeline.cs
@@ -0,0 +1,24 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 构建管线类型
+ ///
+ public enum EBuildPipeline
+ {
+ ///
+ /// 传统内置构建管线 (BBP)
+ ///
+ BuiltinBuildPipeline,
+
+ ///
+ /// 可编程构建管线 (SBP)
+ ///
+ ScriptableBuildPipeline,
+
+ ///
+ /// 原生文件构建管线 (RFBP)
+ ///
+ RawFileBuildPipeline,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/EBuildPipeline.cs.meta b/Editor/AssetBundleBuilder/EBuildPipeline.cs.meta
new file mode 100644
index 0000000..ec277dd
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildPipeline.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e53e56a0f6b01dd4c933249d2bda8d78
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs b/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs
new file mode 100644
index 0000000..0efa8d2
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs
@@ -0,0 +1,34 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 首包资源文件的拷贝方式
+ ///
+ public enum EBuildinFileCopyOption
+ {
+ ///
+ /// 不拷贝任何文件
+ ///
+ None = 0,
+
+ ///
+ /// 先清空已有文件,然后拷贝所有文件
+ ///
+ ClearAndCopyAll,
+
+ ///
+ /// 先清空已有文件,然后按照资源标签拷贝文件
+ ///
+ ClearAndCopyByTags,
+
+ ///
+ /// 不清空已有文件,直接拷贝所有文件
+ ///
+ OnlyCopyAll,
+
+ ///
+ /// 不清空已有文件,直接按照资源标签拷贝文件
+ ///
+ OnlyCopyByTags,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs.meta b/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs.meta
new file mode 100644
index 0000000..605aec0
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EBuildinFileCopyOption.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4defd475b635cdf4b87108140d3a0ad1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/ECompressOption.cs b/Editor/AssetBundleBuilder/ECompressOption.cs
new file mode 100644
index 0000000..2f6d992
--- /dev/null
+++ b/Editor/AssetBundleBuilder/ECompressOption.cs
@@ -0,0 +1,13 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// AssetBundle压缩选项
+ ///
+ public enum ECompressOption
+ {
+ Uncompressed = 0,
+ LZMA,
+ LZ4,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/ECompressOption.cs.meta b/Editor/AssetBundleBuilder/ECompressOption.cs.meta
new file mode 100644
index 0000000..e4fb021
--- /dev/null
+++ b/Editor/AssetBundleBuilder/ECompressOption.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1e8ac0dfc77bd1b4697db63d52ab4c6e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/EFileNameStyle.cs b/Editor/AssetBundleBuilder/EFileNameStyle.cs
new file mode 100644
index 0000000..b6bac71
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EFileNameStyle.cs
@@ -0,0 +1,24 @@
+
+namespace YooAsset.Editor
+{
+ ///
+ /// 补丁包内的文件样式
+ ///
+ public enum EFileNameStyle
+ {
+ ///
+ /// 哈希值名称
+ ///
+ HashName = 0,
+
+ ///
+ /// 资源包名称(不推荐)
+ ///
+ BundleName = 1,
+
+ ///
+ /// 资源包名称 + 哈希值名称
+ ///
+ BundleName_HashName = 2,
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/EFileNameStyle.cs.meta b/Editor/AssetBundleBuilder/EFileNameStyle.cs.meta
new file mode 100644
index 0000000..856af36
--- /dev/null
+++ b/Editor/AssetBundleBuilder/EFileNameStyle.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 84c5eff5dedf53343897e83f6b10eea6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/IBuildPipeline.cs b/Editor/AssetBundleBuilder/IBuildPipeline.cs
new file mode 100644
index 0000000..85d97c0
--- /dev/null
+++ b/Editor/AssetBundleBuilder/IBuildPipeline.cs
@@ -0,0 +1,8 @@
+
+namespace YooAsset.Editor
+{
+ public interface IBuildPipeline
+ {
+ public BuildResult Run(BuildParameters buildParameters, bool enableLog);
+ }
+}
\ No newline at end of file
diff --git a/Editor/AssetBundleBuilder/IBuildPipeline.cs.meta b/Editor/AssetBundleBuilder/IBuildPipeline.cs.meta
new file mode 100644
index 0000000..6fa8d07
--- /dev/null
+++ b/Editor/AssetBundleBuilder/IBuildPipeline.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4c86b6dc67868574ea68f632a1d42180
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/VisualViewers.meta b/Editor/AssetBundleBuilder/VisualViewers.meta
new file mode 100644
index 0000000..3174e91
--- /dev/null
+++ b/Editor/AssetBundleBuilder/VisualViewers.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7c39b7c7b58d79a4a9ee9970e9d0470e
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssetBundleBuilder/VisualViewers/BuildPipelineViewerBase.cs b/Editor/AssetBundleBuilder/VisualViewers/BuildPipelineViewerBase.cs
new file mode 100644
index 0000000..c9798f0
--- /dev/null
+++ b/Editor/AssetBundleBuilder/VisualViewers/BuildPipelineViewerBase.cs
@@ -0,0 +1,214 @@
+#if UNITY_2019_4_OR_NEWER
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using UnityEditor.UIElements;
+using UnityEngine.UIElements;
+
+namespace YooAsset.Editor
+{
+ internal abstract class BuildPipelineViewerBase
+ {
+ private const int StyleWidth = 400;
+
+ protected readonly string PackageName;
+ protected readonly BuildTarget BuildTarget;
+ protected readonly EBuildPipeline BuildPipeline;
+ protected TemplateContainer Root;
+
+ private TextField _buildOutputField;
+ private TextField _buildVersionField;
+ private PopupField _buildModeField;
+ private PopupField _encryptionField;
+ private EnumField _compressionField;
+ private EnumField _outputNameStyleField;
+ private EnumField _copyBuildinFileOptionField;
+ private TextField _copyBuildinFileTagsField;
+
+ public BuildPipelineViewerBase(string packageName, EBuildPipeline buildPipeline, BuildTarget buildTarget, VisualElement parent)
+ {
+ PackageName = packageName;
+ BuildTarget = buildTarget;
+ BuildPipeline = buildPipeline;
+
+ CreateView(parent);
+ RefreshView();
+ }
+ private void CreateView(VisualElement parent)
+ {
+ // 加载布局文件
+ var visualAsset = UxmlLoader.LoadWindowUXML();
+ if (visualAsset == null)
+ return;
+
+ Root = visualAsset.CloneTree();
+ Root.style.flexGrow = 1f;
+ parent.Add(Root);
+
+ // 输出目录
+ string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
+ _buildOutputField = Root.Q("BuildOutput");
+ _buildOutputField.SetValueWithoutNotify(defaultOutputRoot);
+ _buildOutputField.SetEnabled(false);
+
+ // 构建版本
+ _buildVersionField = Root.Q("BuildVersion");
+ _buildVersionField.style.width = StyleWidth;
+ _buildVersionField.SetValueWithoutNotify(GetDefaultPackageVersion());
+
+ // 构建模式
+ {
+ var buildModeContainer = Root.Q("BuildModeContainer");
+ var buildMode = AssetBundleBuilderSetting.GetPackageBuildMode(PackageName, BuildPipeline);
+ var buildModeList = GetSupportBuildModes();
+ int defaultIndex = buildModeList.FindIndex(x => x.Equals(buildMode));
+ if (defaultIndex < 0)
+ defaultIndex = (int)(EBuildMode)buildModeList[0];
+ _buildModeField = new PopupField(buildModeList, defaultIndex);
+ _buildModeField.label = "Build Mode";
+ _buildModeField.style.width = StyleWidth;
+ _buildModeField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageBuildMode(PackageName, BuildPipeline, (EBuildMode)_buildModeField.value);
+ });
+ buildModeContainer.Add(_buildModeField);
+ }
+
+ // 加密方法
+ {
+ var encryptionContainer = Root.Q("EncryptionContainer");
+ var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
+ if (encryptionClassTypes.Count > 0)
+ {
+ var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(PackageName, BuildPipeline);
+ int defaultIndex = encryptionClassTypes.FindIndex(x => x.FullName.Equals(encyptionClassName));
+ if (defaultIndex < 0)
+ defaultIndex = 0;
+ _encryptionField = new PopupField(encryptionClassTypes, defaultIndex);
+ _encryptionField.label = "Encryption";
+ _encryptionField.style.width = StyleWidth;
+ _encryptionField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageEncyptionClassName(PackageName, BuildPipeline, _encryptionField.value.FullName);
+ });
+ encryptionContainer.Add(_encryptionField);
+ }
+ else
+ {
+ _encryptionField = new PopupField();
+ _encryptionField.label = "Encryption";
+ _encryptionField.style.width = StyleWidth;
+ encryptionContainer.Add(_encryptionField);
+ }
+ }
+
+ // 压缩方式选项
+ var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
+ _compressionField = Root.Q("Compression");
+ _compressionField.Init(compressOption);
+ _compressionField.SetValueWithoutNotify(compressOption);
+ _compressionField.style.width = StyleWidth;
+ _compressionField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageCompressOption(PackageName, BuildPipeline, (ECompressOption)_compressionField.value);
+ });
+
+ // 输出文件名称样式
+ var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
+ _outputNameStyleField = Root.Q("FileNameStyle");
+ _outputNameStyleField.Init(fileNameStyle);
+ _outputNameStyleField.SetValueWithoutNotify(fileNameStyle);
+ _outputNameStyleField.style.width = StyleWidth;
+ _outputNameStyleField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageFileNameStyle(PackageName, BuildPipeline, (EFileNameStyle)_outputNameStyleField.value);
+ });
+
+ // 首包文件拷贝选项
+ var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
+ _copyBuildinFileOptionField = Root.Q("CopyBuildinFileOption");
+ _copyBuildinFileOptionField.Init(buildinFileCopyOption);
+ _copyBuildinFileOptionField.SetValueWithoutNotify(buildinFileCopyOption);
+ _copyBuildinFileOptionField.style.width = StyleWidth;
+ _copyBuildinFileOptionField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageBuildinFileCopyOption(PackageName, BuildPipeline, (EBuildinFileCopyOption)_copyBuildinFileOptionField.value);
+ RefreshView();
+ });
+
+ // 首包文件拷贝参数
+ var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
+ _copyBuildinFileTagsField = Root.Q("CopyBuildinFileParam");
+ _copyBuildinFileTagsField.SetValueWithoutNotify(buildinFileCopyParams);
+ _copyBuildinFileTagsField.RegisterValueChangedCallback(evt =>
+ {
+ AssetBundleBuilderSetting.SetPackageBuildinFileCopyParams(PackageName, BuildPipeline, _copyBuildinFileTagsField.value);
+ });
+
+ // 构建按钮
+ var buildButton = Root.Q