Update AssetBundleBuilder

支持可编程构建管线
pull/28/head
hevinci 2022-07-15 19:34:59 +08:00
parent 89022d3df4
commit d1439da54e
21 changed files with 462 additions and 90 deletions

View File

@ -18,29 +18,65 @@ namespace YooAsset.Editor
// 清空旧数据 // 清空旧数据
_buildContext.ClearAllContext(); _buildContext.ClearAllContext();
// 检测构建参数是否为空
if (buildParameters == null)
{
throw new Exception($"{nameof(buildParameters)} is null !");
}
if (buildParameters.BuildPipeline == EBuildPipeline.ScriptBuildPipeline)
{
if (buildParameters.SBPParameters == null)
throw new Exception($"{nameof(BuildParameters.SBPParameters)} is null !");
}
// 构建参数 // 构建参数
var buildParametersContext = new BuildParametersContext(buildParameters); var buildParametersContext = new BuildParametersContext(buildParameters);
_buildContext.SetContextObject(buildParametersContext); _buildContext.SetContextObject(buildParametersContext);
// 执行构建流程 // 是否显示LOG
List<IBuildTask> pipeline = new List<IBuildTask>
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding(), //开始执行构建
new TaskVerifyBuildResult(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskCreatePatchManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件
new TaskCreatePatchPackage(), //制作补丁包
new TaskCopyBuildinFiles(), //拷贝内置文件
};
if (buildParameters.BuildMode == EBuildMode.SimulateBuild) if (buildParameters.BuildMode == EBuildMode.SimulateBuild)
BuildRunner.EnableLog = false; BuildRunner.EnableLog = false;
else else
BuildRunner.EnableLog = true; BuildRunner.EnableLog = true;
// 创建构建节点
List<IBuildTask> pipeline;
if (buildParameters.BuildPipeline == EBuildPipeline.BuiltInBuildPipeline)
{
pipeline = new List<IBuildTask>
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding(), //开始执行构建
new TaskVerifyBuildResult(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskCreatePatchManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件
new TaskCreatePatchPackage(), //制作补丁包
new TaskCopyBuildinFiles(), //拷贝内置文件
};
}
else if (buildParameters.BuildPipeline == EBuildPipeline.ScriptBuildPipeline)
{
pipeline = new List<IBuildTask>
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding_SBP(), //开始执行构建
new TaskVerifyBuildResult_SBP(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskCreatePatchManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件
new TaskCreatePatchPackage(), //制作补丁包
new TaskCopyBuildinFiles(), //拷贝内置文件
};
}
else
{
throw new NotImplementedException();
}
// 执行构建流程
bool succeed = BuildRunner.Run(pipeline, _buildContext); bool succeed = BuildRunner.Run(pipeline, _buildContext);
if (succeed) if (succeed)
Debug.Log($"{buildParameters.BuildMode} pipeline build succeed !"); Debug.Log($"{buildParameters.BuildMode} pipeline build succeed !");

View File

@ -10,6 +10,11 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public int BuildVersion = 0; public int BuildVersion = 0;
/// <summary>
/// 构建管线
/// </summary>
public EBuildPipeline BuildPipeline = EBuildPipeline.BuiltInBuildPipeline;
/// <summary> /// <summary>
/// 构建模式 /// 构建模式
/// </summary> /// </summary>

View File

@ -24,6 +24,7 @@ namespace YooAsset.Editor
private TextField _buildOutputField; private TextField _buildOutputField;
private IntegerField _buildVersionField; private IntegerField _buildVersionField;
private EnumField _buildPipelineField;
private EnumField _buildModeField; private EnumField _buildModeField;
private TextField _buildinTagsField; private TextField _buildinTagsField;
private PopupField<string> _encryptionField; private PopupField<string> _encryptionField;
@ -62,6 +63,17 @@ namespace YooAsset.Editor
AssetBundleBuilderSettingData.Setting.BuildVersion = _buildVersionField.value; AssetBundleBuilderSettingData.Setting.BuildVersion = _buildVersionField.value;
}); });
// 构建管线
_buildPipelineField = root.Q<EnumField>("BuildPipeline");
_buildPipelineField.Init(AssetBundleBuilderSettingData.Setting.BuildPipeline);
_buildPipelineField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.BuildPipeline);
_buildPipelineField.style.width = 300;
_buildPipelineField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.Setting.BuildPipeline = (EBuildPipeline)_buildPipelineField.value;
RefreshWindow();
});
// 构建模式 // 构建模式
_buildModeField = root.Q<EnumField>("BuildMode"); _buildModeField = root.Q<EnumField>("BuildMode");
_buildModeField.Init(AssetBundleBuilderSettingData.Setting.BuildMode); _buildModeField.Init(AssetBundleBuilderSettingData.Setting.BuildMode);
@ -165,23 +177,28 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
private void ExecuteBuild() private void ExecuteBuild()
{ {
var buildMode = (EBuildMode)_buildModeField.value;
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultOutputRoot(); string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultOutputRoot();
BuildParameters buildParameters = new BuildParameters(); BuildParameters buildParameters = new BuildParameters();
buildParameters.OutputRoot = defaultOutputRoot; buildParameters.OutputRoot = defaultOutputRoot;
buildParameters.BuildTarget = _buildTarget; buildParameters.BuildTarget = _buildTarget;
buildParameters.BuildMode = buildMode; buildParameters.BuildPipeline = AssetBundleBuilderSettingData.Setting.BuildPipeline;
buildParameters.BuildVersion = _buildVersionField.value; buildParameters.BuildMode = AssetBundleBuilderSettingData.Setting.BuildMode;
buildParameters.BuildinTags = _buildinTagsField.value; buildParameters.BuildVersion = AssetBundleBuilderSettingData.Setting.BuildVersion;
buildParameters.BuildinTags = AssetBundleBuilderSettingData.Setting.BuildTags;
buildParameters.VerifyBuildingResult = true; buildParameters.VerifyBuildingResult = true;
buildParameters.EnableAddressable = AssetBundleCollectorSettingData.Setting.EnableAddressable; buildParameters.EnableAddressable = AssetBundleCollectorSettingData.Setting.EnableAddressable;
buildParameters.AppendFileExtension = _appendExtensionToggle.value; buildParameters.AppendFileExtension = AssetBundleBuilderSettingData.Setting.AppendExtension;
buildParameters.CopyBuildinTagFiles = buildMode == EBuildMode.ForceRebuild; buildParameters.CopyBuildinTagFiles = AssetBundleBuilderSettingData.Setting.BuildMode == EBuildMode.ForceRebuild;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance(); buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.CompressOption = (ECompressOption)_compressionField.value; buildParameters.CompressOption = AssetBundleBuilderSettingData.Setting.CompressOption;
AssetBundleBuilder builder = new AssetBundleBuilder(); if (AssetBundleBuilderSettingData.Setting.BuildPipeline == EBuildPipeline.ScriptBuildPipeline)
{
buildParameters.SBPParameters = new BuildParameters.SBPBuildParameters();
buildParameters.SBPParameters.WriteLinkXML = true;
}
var builder = new AssetBundleBuilder();
bool succeed = builder.Run(buildParameters); bool succeed = builder.Run(buildParameters);
if (succeed) if (succeed)
{ {

View File

@ -3,6 +3,7 @@
<ui:VisualElement name="BuildContainer"> <ui:VisualElement name="BuildContainer">
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" /> <ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
<uie:IntegerField label="Build Version" value="0" name="BuildVersion" /> <uie:IntegerField label="Build Version" value="0" name="BuildVersion" />
<uie:EnumField label="Build Pipeline" name="BuildPipeline" />
<uie:EnumField label="Build Mode" name="BuildMode" /> <uie:EnumField label="Build Mode" name="BuildMode" />
<ui:VisualElement name="EncryptionContainer" style="height: 24px;" /> <ui:VisualElement name="EncryptionContainer" style="height: 24px;" />
<uie:EnumField label="Compression" value="Center" name="Compression" /> <uie:EnumField label="Compression" value="Center" name="Compression" />

View File

@ -9,6 +9,23 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public class BuildParameters public class BuildParameters
{ {
/// <summary>
/// SBP构建参数
/// </summary>
public class SBPBuildParameters
{
/// <summary>
/// 生成代码防裁剪配置
/// </summary>
public bool WriteLinkXML = true;
}
/// <summary>
/// 可编程构建管线的参数
/// </summary>
public SBPBuildParameters SBPParameters;
/// <summary> /// <summary>
/// 输出的根目录 /// 输出的根目录
/// </summary> /// </summary>
@ -19,6 +36,11 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public BuildTarget BuildTarget; public BuildTarget BuildTarget;
/// <summary>
/// 构建管线
/// </summary>
public EBuildPipeline BuildPipeline;
/// <summary> /// <summary>
/// 构建模式 /// 构建模式
/// </summary> /// </summary>
@ -86,4 +108,6 @@ namespace YooAsset.Editor
return StringUtility.StringToStringList(BuildinTags, ';'); return StringUtility.StringToStringList(BuildinTags, ';');
} }
} }
} }

View File

@ -40,19 +40,19 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 获取构建选项 /// 获取内置构建管线的构建选项
/// </summary> /// </summary>
public BuildAssetBundleOptions GetPipelineBuildOptions() public BuildAssetBundleOptions GetPipelineBuildOptions()
{ {
// For the new build system, unity always need BuildAssetBundleOptions.CollectDependencies and BuildAssetBundleOptions.DeterministicAssetBundle // For the new build system, unity always need BuildAssetBundleOptions.CollectDependencies and BuildAssetBundleOptions.DeterministicAssetBundle
// 除非设置ForceRebuildAssetBundle标记否则会进行增量打包 // 除非设置ForceRebuildAssetBundle标记否则会进行增量打包
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
if (Parameters.BuildMode == EBuildMode.SimulateBuild) if (Parameters.BuildMode == EBuildMode.SimulateBuild)
throw new Exception("Should never get here !"); throw new Exception("Should never get here !");
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
if (Parameters.BuildMode == EBuildMode.DryRunBuild) if (Parameters.BuildMode == EBuildMode.DryRunBuild)
{ {
opt |= BuildAssetBundleOptions.DryRunBuild; opt |= BuildAssetBundleOptions.DryRunBuild;
@ -77,6 +77,39 @@ namespace YooAsset.Editor
return opt; return opt;
} }
/// <summary>
/// 获取可编程构建管线的构建参数
/// </summary>
public UnityEditor.Build.Pipeline.BundleBuildParameters GetSBPBuildParameters()
{
if (Parameters.BuildMode == EBuildMode.SimulateBuild)
throw new Exception("Should never get here !");
if (Parameters.BuildMode == EBuildMode.DryRunBuild)
throw new Exception($"SBP not support {nameof(EBuildMode.DryRunBuild)} build mode !");
var targetGroup = BuildPipeline.GetBuildTargetGroup(Parameters.BuildTarget);
var buildParams = new UnityEditor.Build.Pipeline.BundleBuildParameters(Parameters.BuildTarget, targetGroup, PipelineOutputDirectory);
if (Parameters.CompressOption == ECompressOption.Uncompressed)
buildParams.BundleCompression = UnityEngine.BuildCompression.Uncompressed;
else if (Parameters.CompressOption == ECompressOption.LZMA)
buildParams.BundleCompression = UnityEngine.BuildCompression.LZMA;
else if (Parameters.CompressOption == ECompressOption.LZ4)
buildParams.BundleCompression = UnityEngine.BuildCompression.LZ4;
else
throw new System.NotImplementedException(Parameters.CompressOption.ToString());
if (Parameters.BuildMode == EBuildMode.ForceRebuild)
buildParams.UseCache = false;
if (Parameters.DisableWriteTypeTree)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;
buildParams.WriteLinkXML = Parameters.SBPParameters.WriteLinkXML;
return buildParams;
}
/// <summary> /// <summary>
/// 获取构建的耗时(单位:秒) /// 获取构建的耗时(单位:秒)
/// </summary> /// </summary>

View File

@ -8,6 +8,11 @@ namespace YooAsset.Editor
[Serializable] [Serializable]
public class ReportSummary public class ReportSummary
{ {
/// <summary>
/// YooAsset版本
/// </summary>
public string YooVersion;
/// <summary> /// <summary>
/// 引擎版本 /// 引擎版本
/// </summary> /// </summary>
@ -16,7 +21,7 @@ namespace YooAsset.Editor
/// <summary> /// <summary>
/// 构建时间 /// 构建时间
/// </summary> /// </summary>
public string BuildTime; public string BuildDate;
/// <summary> /// <summary>
/// 构建耗时(单位:秒) /// 构建耗时(单位:秒)
@ -28,6 +33,11 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public BuildTarget BuildTarget; public BuildTarget BuildTarget;
/// <summary>
/// 构建管线
/// </summary>
public EBuildPipeline BuildPipeline;
/// <summary> /// <summary>
/// 构建模式 /// 构建模式
/// </summary> /// </summary>

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Linq; using System.Linq;
using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor; using UnityEditor;

View File

@ -0,0 +1,82 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build.Pipeline;
using UnityEditor.Build.Pipeline.Interfaces;
namespace YooAsset.Editor
{
[TaskAttribute("资源构建内容打包")]
public class TaskBuilding_SBP : IBuildTask
{
public class SBPBuildResultContext : IContextObject
{
public IBundleBuildResults Results;
}
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
// 模拟构建模式下跳过引擎构建
var buildMode = buildParametersContext.Parameters.BuildMode;
if (buildMode == EBuildMode.SimulateBuild)
return;
// 构建内容
var buildContent = new BundleBuildContent(buildMapContext.GetPipelineBuilds());
// 开始构建
IBundleBuildResults buildResults;
var buildParameters = buildParametersContext.GetSBPBuildParameters();
var taskList = DefaultBuildTasks.Create(DefaultBuildTasks.Preset.AssetBundleBuiltInShaderExtraction);
ReturnCode exitCode = ContentPipeline.BuildAssetBundles(buildParameters, buildContent, out buildResults, taskList);
if (exitCode < 0)
{
throw new Exception($"构建过程中发生错误 : {exitCode}");
}
BuildRunner.Log("Unity引擎打包成功");
SBPBuildResultContext buildResultContext = new SBPBuildResultContext();
buildResultContext.Results = buildResults;
context.SetContextObject(buildResultContext);
// 添加Unity内置资源包信息
if (buildResults.BundleInfos.Keys.Any(t => t == YooAssetSettings.UnityBuiltInShadersBundleName))
{
BuildBundleInfo builtInBundleInfo = new BuildBundleInfo(YooAssetSettings.UnityBuiltInShadersBundleName);
buildMapContext.BundleInfos.Add(builtInBundleInfo);
}
// 拷贝原生文件
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
{
CopyRawBundle(buildMapContext, buildParametersContext);
}
}
/// <summary>
/// 拷贝原生文件
/// </summary>
private void CopyRawBundle(BuildMapContext buildMapContext, BuildParametersContext buildParametersContext)
{
foreach (var bundleInfo in buildMapContext.BundleInfos)
{
if (bundleInfo.IsRawFile)
{
string dest = $"{buildParametersContext.PipelineOutputDirectory}/{bundleInfo.BundleName}";
foreach (var buildAsset in bundleInfo.BuildinAssets)
{
if (buildAsset.IsRawAsset)
EditorTools.CopyFile(buildAsset.AssetPath, dest, true);
}
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1af5fed7e9f83174d868c12b41c4a79e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,11 @@
using System; using System;
using System.IO; using System.Linq;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor.Build.Pipeline;
using UnityEditor.Build.Pipeline.Interfaces;
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
[TaskAttribute("创建补丁清单文件")] [TaskAttribute("创建补丁清单文件")]
@ -10,18 +13,17 @@ namespace YooAsset.Editor
{ {
void IBuildTask.Run(BuildContext context) void IBuildTask.Run(BuildContext context)
{ {
var buildParameters = context.GetContextObject<BuildParametersContext>(); CreatePatchManifestFile(context);
var buildMapContext = context.GetContextObject<BuildMapContext>();
var encryptionContext = context.GetContextObject<TaskEncryption.EncryptionContext>();
CreatePatchManifestFile(buildParameters, buildMapContext, encryptionContext);
} }
/// <summary> /// <summary>
/// 创建补丁清单文件到输出目录 /// 创建补丁清单文件到输出目录
/// </summary> /// </summary>
private void CreatePatchManifestFile(BuildParametersContext buildParameters, BuildMapContext buildMapContext, private void CreatePatchManifestFile(BuildContext context)
TaskEncryption.EncryptionContext encryptionContext)
{ {
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
var encryptionContext = context.GetContextObject<TaskEncryption.EncryptionContext>();
int resourceVersion = buildParameters.Parameters.BuildVersion; int resourceVersion = buildParameters.Parameters.BuildVersion;
// 创建新补丁清单 // 创建新补丁清单
@ -32,6 +34,13 @@ namespace YooAsset.Editor
patchManifest.BundleList = GetAllPatchBundle(buildParameters, buildMapContext, encryptionContext); patchManifest.BundleList = GetAllPatchBundle(buildParameters, buildMapContext, encryptionContext);
patchManifest.AssetList = GetAllPatchAsset(buildParameters, buildMapContext, patchManifest); patchManifest.AssetList = GetAllPatchAsset(buildParameters, buildMapContext, patchManifest);
// 更新Unity内置资源包的引用关系
if (buildParameters.Parameters.BuildPipeline == EBuildPipeline.ScriptBuildPipeline)
{
var buildResultContext = context.GetContextObject<TaskBuilding_SBP.SBPBuildResultContext>();
UpdateBuiltInBundleReference(patchManifest, buildResultContext.Results);
}
// 创建补丁清单文件 // 创建补丁清单文件
string manifestFilePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(resourceVersion)}"; string manifestFilePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(resourceVersion)}";
BuildRunner.Log($"创建补丁清单文件:{manifestFilePath}"); BuildRunner.Log($"创建补丁清单文件:{manifestFilePath}");
@ -172,5 +181,45 @@ namespace YooAsset.Editor
} }
throw new Exception($"Not found bundle name : {bundleName}"); throw new Exception($"Not found bundle name : {bundleName}");
} }
/// <summary>
/// 更新Unity内置资源包的引用关系
/// </summary>
private void UpdateBuiltInBundleReference(PatchManifest patchManifest, IBundleBuildResults buildResults)
{
// 获取所有依赖内置资源包的资源包列表
List<string> builtInBundleReferenceList = new List<string>();
foreach (var valuePair in buildResults.BundleInfos)
{
if (valuePair.Value.Dependencies.Any(t => t == YooAssetSettings.UnityBuiltInShadersBundleName))
builtInBundleReferenceList.Add(valuePair.Key);
}
// 检测依赖交集并更新依赖ID
int builtInBundleId = patchManifest.BundleList.Count - 1;
foreach (var patchAsset in patchManifest.AssetList)
{
List<string> dependBundles = GetPatchAssetAllDependBundles(patchManifest, patchAsset);
List<string> conflictAssetPathList = dependBundles.Intersect(builtInBundleReferenceList).ToList();
if (conflictAssetPathList.Count > 0)
{
List<int> newDependIDs = new List<int>(patchAsset.DependIDs);
newDependIDs.Add(builtInBundleId);
patchAsset.DependIDs = newDependIDs.ToArray();
}
}
}
private List<string> GetPatchAssetAllDependBundles(PatchManifest patchManifest, PatchAsset patchAsset)
{
List<string> result = new List<string>();
string mainBundle = patchManifest.BundleList[patchAsset.BundleID].BundleName;
result.Add(mainBundle);
foreach (var dependID in patchAsset.DependIDs)
{
string dependBundle = patchManifest.BundleList[dependID].BundleName;
result.Add(dependBundle);
}
return result;
}
} }
} }

View File

@ -54,18 +54,38 @@ namespace YooAsset.Editor
EditorTools.CopyFile(sourcePath, destPath, true); EditorTools.CopyFile(sourcePath, destPath, true);
} }
// 拷贝UnityManifest序列化文件 if (buildParameters.Parameters.BuildPipeline == EBuildPipeline.ScriptBuildPipeline)
{ {
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}"; // 拷贝构建日志
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}"; {
EditorTools.CopyFile(sourcePath, destPath, true); string sourcePath = $"{buildParameters.PipelineOutputDirectory}/buildlogtep.json";
} string destPath = $"{packageDirectory}/buildlogtep.json";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝UnityManifest文本文件 // 拷贝代码防裁剪配置
if (buildParameters.Parameters.SBPParameters.WriteLinkXML)
{
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/link.xml";
string destPath = $"{packageDirectory}/link.xml";
EditorTools.CopyFile(sourcePath, destPath, true);
}
}
else
{ {
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest"; // 拷贝UnityManifest序列化文件
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest"; {
EditorTools.CopyFile(sourcePath, destPath, true); string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}";
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝UnityManifest文本文件
{
string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest";
string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest";
EditorTools.CopyFile(sourcePath, destPath, true);
}
} }
// 拷贝所有补丁文件 // 拷贝所有补丁文件

View File

@ -29,14 +29,20 @@ namespace YooAsset.Editor
private void CreateReportFile(BuildParametersContext buildParameters, BuildMapContext buildMapContext) private void CreateReportFile(BuildParametersContext buildParameters, BuildMapContext buildMapContext)
{ {
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory, buildParameters.Parameters.BuildVersion); PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory, buildParameters.Parameters.BuildVersion);
BuildReport buildReport = new BuildReport(); 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.UnityVersion = UnityEngine.Application.unityVersion;
buildReport.Summary.BuildTime = DateTime.Now.ToString(); buildReport.Summary.BuildDate = DateTime.Now.ToString();
buildReport.Summary.BuildSeconds = (int)buildParameters.GetBuildingSeconds(); buildReport.Summary.BuildSeconds = (int)buildParameters.GetBuildingSeconds();
buildReport.Summary.BuildTarget = buildParameters.Parameters.BuildTarget; buildReport.Summary.BuildTarget = buildParameters.Parameters.BuildTarget;
buildReport.Summary.BuildPipeline = buildParameters.Parameters.BuildPipeline;
buildReport.Summary.BuildMode = buildParameters.Parameters.BuildMode; buildReport.Summary.BuildMode = buildParameters.Parameters.BuildMode;
buildReport.Summary.BuildVersion = buildParameters.Parameters.BuildVersion; buildReport.Summary.BuildVersion = buildParameters.Parameters.BuildVersion;
buildReport.Summary.BuildinTags = buildParameters.Parameters.BuildinTags; buildReport.Summary.BuildinTags = buildParameters.Parameters.BuildinTags;

View File

@ -37,53 +37,21 @@ namespace YooAsset.Editor
string[] buildedBundles = unityManifest.GetAllAssetBundles(); string[] buildedBundles = unityManifest.GetAllAssetBundles();
// 1. 过滤掉原生Bundle // 1. 过滤掉原生Bundle
List<BuildBundleInfo> expectBundles = new List<BuildBundleInfo>(buildedBundles.Length); string[] expectBundles = buildMapContext.BundleInfos.Where(t => t.IsRawFile == false).Select(t => t.BundleName).ToArray();
foreach(var bundleInfo in buildMapContext.BundleInfos)
{
if (bundleInfo.IsRawFile == false)
expectBundles.Add(bundleInfo);
}
// 2. 验证数量 // 2. 验证Bundle
if (buildedBundles.Length != expectBundles.Count) List<string> intersectBundleList = buildedBundles.Except(expectBundles).ToList();
if (intersectBundleList.Count > 0)
{ {
Debug.LogWarning($"构建过程中可能存在无效的资源导致和预期构建的Bundle数量不一致"); foreach (var intersectBundle in intersectBundleList)
}
// 3. 正向验证Bundle
foreach (var bundleName in buildedBundles)
{
if (buildMapContext.IsContainsBundle(bundleName) == false)
{ {
throw new Exception($"Should never get here !"); Debug.LogWarning($"差异资源包: {intersectBundle}");
} }
throw new System.Exception("存在差异资源包!请查看警告信息!");
} }
// 4. 反向验证Bundle // 3. 验证Asset
bool isPass = true; bool isPass = true;
foreach (var expectBundle in expectBundles)
{
bool isMatch = false;
foreach (var buildedBundle in buildedBundles)
{
if (buildedBundle == expectBundle.BundleName)
{
isMatch = true;
break;
}
}
if (isMatch == false)
{
isPass = false;
Debug.LogWarning($"没有找到预期构建的Bundle文件 : {expectBundle.BundleName}");
}
}
if(isPass == false)
{
throw new Exception("构建结果验证没有通过,请参考警告日志!");
}
// 5. 验证Asset
var buildMode = buildParameters.Parameters.BuildMode; var buildMode = buildParameters.Parameters.BuildMode;
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild) if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
{ {
@ -137,7 +105,6 @@ namespace YooAsset.Editor
} }
} }
// 卸载所有加载的Bundle
BuildRunner.Log("构建结果验证成功!"); BuildRunner.Log("构建结果验证成功!");
} }

View File

@ -0,0 +1,60 @@
using System;
using System.Linq;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.Build.Pipeline.Interfaces;
namespace YooAsset.Editor
{
[TaskAttribute("验证构建结果")]
public class TaskVerifyBuildResult_SBP : IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
// 模拟构建模式下跳过验证
if (buildParametersContext.Parameters.BuildMode == EBuildMode.SimulateBuild)
return;
// 验证构建结果
if (buildParametersContext.Parameters.VerifyBuildingResult)
{
var buildResultContext = context.GetContextObject<TaskBuilding_SBP.SBPBuildResultContext>();
VerifyingBuildingResult(context, buildResultContext.Results);
}
}
/// <summary>
/// 验证构建结果
/// </summary>
private void VerifyingBuildingResult(BuildContext context, IBundleBuildResults buildResults)
{
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
// 1. 移除特定Bundle
List<string> buildedBundles = buildResults.BundleInfos.Keys.ToList();
buildedBundles.Remove(YooAssetSettings.UnityBuiltInShadersBundleName);
// 2. 过滤掉原生Bundle
List<string> expectBundles = buildMapContext.BundleInfos.Where(t => t.IsRawFile == false).Select(t => t.BundleName).ToList();
// 3. 验证Bundle
List<string> intersectBundleList = buildedBundles.Except(expectBundles).ToList();
if (intersectBundleList.Count > 0)
{
foreach (var intersectBundle in intersectBundleList)
{
Debug.LogWarning($"差异资源包: {intersectBundle}");
}
throw new System.Exception("存在差异资源包!请查看警告信息!");
}
BuildRunner.Log("构建结果验证成功!");
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16aa7c2c37209a043b4f33d7854047c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@

namespace YooAsset.Editor
{
/// <summary>
/// 构建管线类型
/// </summary>
public enum EBuildPipeline
{
/// <summary>
/// 传统内置构建管线
/// </summary>
BuiltInBuildPipeline,
/// <summary>
/// 可编程构建管线
/// </summary>
ScriptBuildPipeline,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e53e56a0f6b01dd4c933249d2bda8d78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -58,10 +58,13 @@ namespace YooAsset.Editor
_buildReport = buildReport; _buildReport = buildReport;
_items.Clear(); _items.Clear();
_items.Add(new ItemWrapper("YooAsset版本", buildReport.Summary.YooVersion));
_items.Add(new ItemWrapper("引擎版本", buildReport.Summary.UnityVersion)); _items.Add(new ItemWrapper("引擎版本", buildReport.Summary.UnityVersion));
_items.Add(new ItemWrapper("构建时间", buildReport.Summary.BuildTime)); _items.Add(new ItemWrapper("构建时间", buildReport.Summary.BuildDate));
_items.Add(new ItemWrapper("构建耗时", $"{buildReport.Summary.BuildSeconds}秒")); _items.Add(new ItemWrapper("构建耗时", $"{buildReport.Summary.BuildSeconds}秒"));
_items.Add(new ItemWrapper("构建平台", $"{buildReport.Summary.BuildTarget}")); _items.Add(new ItemWrapper("构建平台", $"{buildReport.Summary.BuildTarget}"));
_items.Add(new ItemWrapper("构建管线", $"{buildReport.Summary.BuildPipeline}"));
_items.Add(new ItemWrapper("构建模式", $"{buildReport.Summary.BuildMode}")); _items.Add(new ItemWrapper("构建模式", $"{buildReport.Summary.BuildMode}"));
_items.Add(new ItemWrapper("构建版本", $"{buildReport.Summary.BuildVersion}")); _items.Add(new ItemWrapper("构建版本", $"{buildReport.Summary.BuildVersion}"));
_items.Add(new ItemWrapper("内置资源标签", $"{buildReport.Summary.BuildinTags}")); _items.Add(new ItemWrapper("内置资源标签", $"{buildReport.Summary.BuildinTags}"));

View File

@ -2,7 +2,9 @@
"name": "YooAsset.Editor", "name": "YooAsset.Editor",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"YooAsset" "YooAsset",
"Unity.ScriptableBuildPipeline",
"Unity.ScriptableBuildPipeline.Editor"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"

View File

@ -25,6 +25,7 @@ namespace YooAsset
/// </summary> /// </summary>
public string UnityManifestFileName = "UnityManifest"; public string UnityManifestFileName = "UnityManifest";
/// <summary> /// <summary>
/// 构建输出的报告文件 /// 构建输出的报告文件
/// </summary> /// </summary>
@ -34,5 +35,10 @@ namespace YooAsset
/// 静态版本文件 /// 静态版本文件
/// </summary> /// </summary>
public const string VersionFileName = "StaticVersion.bytes"; public const string VersionFileName = "StaticVersion.bytes";
/// <summary>
/// Unity内置着色器资源包名称
/// </summary>
public const string UnityBuiltInShadersBundleName = "UnityBuiltInShaders.bundle";
} }
} }