2022-03-01 10:44:12 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace YooAsset.Editor
|
|
|
|
|
|
{
|
|
|
|
|
|
public class TaskBuilding : IBuildTask
|
|
|
|
|
|
{
|
|
|
|
|
|
public class UnityManifestContext : IContextObject
|
|
|
|
|
|
{
|
|
|
|
|
|
public AssetBundleManifest UnityManifest;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IBuildTask.Run(BuildContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
var buildParametersContext = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
2022-04-02 15:12:08 +08:00
|
|
|
|
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
Debug.Log($"开始构建......");
|
|
|
|
|
|
BuildAssetBundleOptions opt = buildParametersContext.GetPipelineBuildOptions();
|
|
|
|
|
|
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(buildParametersContext.PipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), opt, buildParametersContext.Parameters.BuildTarget);
|
|
|
|
|
|
if (unityManifest == null)
|
|
|
|
|
|
throw new Exception("构建过程中发生错误!");
|
|
|
|
|
|
|
|
|
|
|
|
UnityManifestContext unityManifestContext = new UnityManifestContext();
|
|
|
|
|
|
unityManifestContext.UnityManifest = unityManifest;
|
|
|
|
|
|
context.SetContextObject(unityManifestContext);
|
|
|
|
|
|
|
|
|
|
|
|
// 拷贝原生文件
|
2022-03-16 22:25:55 +08:00
|
|
|
|
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (bundleInfo.IsRawFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
string dest = $"{buildParametersContext.PipelineOutputDirectory}/{bundleInfo.BundleName}";
|
2022-03-17 21:52:08 +08:00
|
|
|
|
foreach(var buildAsset in bundleInfo.BuildinAssets)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
if(buildAsset.IsRawAsset)
|
|
|
|
|
|
EditorTools.CopyFile(buildAsset.AssetPath, dest, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证构建结果
|
2022-03-19 00:41:50 +08:00
|
|
|
|
if (buildParametersContext.Parameters.VerifyBuildingResult)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
VerifyingBuildingResult(context, unityManifest);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 验证构建结果
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
|
|
|
|
|
|
{
|
|
|
|
|
|
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
2022-04-02 15:12:08 +08:00
|
|
|
|
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
2022-03-01 10:44:12 +08:00
|
|
|
|
string[] buildedBundles = unityManifest.GetAllAssetBundles();
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 过滤掉原生Bundle
|
|
|
|
|
|
List<BuildBundleInfo> expectBundles = new List<BuildBundleInfo>(buildedBundles.Length);
|
2022-03-16 22:25:55 +08:00
|
|
|
|
foreach(var bundleInfo in buildMapContext.BundleInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (bundleInfo.IsRawFile == false)
|
|
|
|
|
|
expectBundles.Add(bundleInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 验证数量
|
|
|
|
|
|
if (buildedBundles.Length != expectBundles.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"构建过程中可能存在无效的资源,导致和预期构建的Bundle数量不一致!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 正向验证Bundle
|
|
|
|
|
|
foreach (var bundleName in buildedBundles)
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
if (buildMapContext.IsContainsBundle(bundleName) == false)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
throw new Exception($"Should never get here !");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 反向验证Bundle
|
|
|
|
|
|
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
|
|
|
|
|
|
int progressValue = 0;
|
|
|
|
|
|
foreach (var buildedBundle in buildedBundles)
|
|
|
|
|
|
{
|
|
|
|
|
|
string filePath = $"{buildParameters.PipelineOutputDirectory}/{buildedBundle}";
|
|
|
|
|
|
string[] allBuildinAssetPaths = GetAssetBundleAllAssets(filePath);
|
|
|
|
|
|
string[] expectBuildinAssetPaths = buildMapContext.GetBuildinAssetPaths(buildedBundle);
|
|
|
|
|
|
if (expectBuildinAssetPaths.Length != allBuildinAssetPaths.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"构建的Bundle文件内的资源对象数量和预期不匹配 : {buildedBundle}");
|
|
|
|
|
|
isPass = false;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var buildinAssetPath in allBuildinAssetPaths)
|
|
|
|
|
|
{
|
|
|
|
|
|
var guid = AssetDatabase.AssetPathToGUID(buildinAssetPath);
|
|
|
|
|
|
if (string.IsNullOrEmpty(guid))
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"无效的资源路径,请检查路径是否带有特殊符号或中文:{buildinAssetPath}");
|
|
|
|
|
|
isPass = false;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool isMatch = false;
|
|
|
|
|
|
foreach (var exceptBuildAssetPath in expectBuildinAssetPaths)
|
|
|
|
|
|
{
|
|
|
|
|
|
var guidExcept = AssetDatabase.AssetPathToGUID(exceptBuildAssetPath);
|
|
|
|
|
|
if (guid == guidExcept)
|
|
|
|
|
|
{
|
|
|
|
|
|
isMatch = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (isMatch == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"在构建的Bundle文件里发现了没有匹配的资源对象:{buildinAssetPath}");
|
|
|
|
|
|
isPass = false;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorTools.DisplayProgressBar("验证构建结果", ++progressValue, buildedBundles.Length);
|
|
|
|
|
|
}
|
|
|
|
|
|
EditorTools.ClearProgressBar();
|
|
|
|
|
|
if (isPass == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("构建结果验证没有通过,请参考警告日志!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 卸载所有加载的Bundle
|
|
|
|
|
|
Debug.Log("构建结果验证成功!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 解析.manifest文件并获取资源列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string[] GetAssetBundleAllAssets(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
string manifestFilePath = $"{filePath}.manifest";
|
|
|
|
|
|
List<string> assetLines = new List<string>();
|
|
|
|
|
|
using (StreamReader reader = File.OpenText(manifestFilePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
string content;
|
|
|
|
|
|
bool findTarget = false;
|
|
|
|
|
|
while (null != (content = reader.ReadLine()))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (content.StartsWith("Dependencies:"))
|
|
|
|
|
|
break;
|
|
|
|
|
|
if (findTarget == false && content.StartsWith("Assets:"))
|
|
|
|
|
|
findTarget = true;
|
|
|
|
|
|
if (findTarget)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (content.StartsWith("- "))
|
|
|
|
|
|
{
|
|
|
|
|
|
string assetPath = content.TrimStart("- ".ToCharArray());
|
|
|
|
|
|
assetLines.Add(assetPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return assetLines.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|