2022-03-01 10:44:12 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
|
|
|
|
|
|
namespace YooAsset.Editor
|
|
|
|
|
|
{
|
|
|
|
|
|
public class TaskGetBuildMap : IBuildTask
|
|
|
|
|
|
{
|
|
|
|
|
|
public class BuildMapContext : IContextObject
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 资源包列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public readonly List<BuildBundleInfo> BundleInfos = new List<BuildBundleInfo>(1000);
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 冗余的资源列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public readonly List<string> RedundancyList = new List<string>(1000);
|
|
|
|
|
|
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加一个打包资源
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void PackAsset(BuildAssetInfo assetInfo)
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
if (TryGetBundleInfo(assetInfo.BundleName, out BuildBundleInfo bundleInfo))
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
bundleInfo.PackAsset(assetInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2022-03-16 17:35:21 +08:00
|
|
|
|
BuildBundleInfo newBundleInfo = new BuildBundleInfo(assetInfo.BundleName);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
newBundleInfo.PackAsset(assetInfo);
|
2022-03-16 22:25:55 +08:00
|
|
|
|
BundleInfos.Add(newBundleInfo);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取所有的打包资源
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public List<BuildAssetInfo> GetAllAssets()
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
List<BuildAssetInfo> result = new List<BuildAssetInfo>(BundleInfos.Count);
|
|
|
|
|
|
foreach (var bundleInfo in BundleInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
result.AddRange(bundleInfo.Assets);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取AssetBundle内包含的标记列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string[] GetAssetTags(string bundleFullName)
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
if (TryGetBundleInfo(bundleFullName, out BuildBundleInfo bundleInfo))
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
return bundleInfo.GetAssetTags();
|
|
|
|
|
|
}
|
|
|
|
|
|
throw new Exception($"Not found {nameof(BuildBundleInfo)} : {bundleFullName}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取AssetBundle内构建的资源路径列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string[] GetBuildinAssetPaths(string bundleFullName)
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
if (TryGetBundleInfo(bundleFullName, out BuildBundleInfo bundleInfo))
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
return bundleInfo.GetBuildinAssetPaths();
|
|
|
|
|
|
}
|
|
|
|
|
|
throw new Exception($"Not found {nameof(BuildBundleInfo)} : {bundleFullName}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取构建管线里需要的数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(BundleInfos.Count);
|
|
|
|
|
|
foreach (var bundleInfo in BundleInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (bundleInfo.IsRawFile == false)
|
|
|
|
|
|
builds.Add(bundleInfo.CreatePipelineBuild());
|
|
|
|
|
|
}
|
|
|
|
|
|
return builds.ToArray();
|
|
|
|
|
|
}
|
2022-03-16 22:25:55 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 是否包含资源包
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsContainsBundle(string bundleFullName)
|
|
|
|
|
|
{
|
|
|
|
|
|
return TryGetBundleInfo(bundleFullName, out BuildBundleInfo bundleInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool TryGetBundleInfo(string bundleFullName, out BuildBundleInfo result)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var bundleInfo in BundleInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bundleInfo.BundleName == bundleFullName)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = bundleInfo;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
result = null;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void IBuildTask.Run(BuildContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
var buildParametersContext = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
|
|
|
|
|
|
BuildMapContext buildMapContext = new BuildMapContext();
|
|
|
|
|
|
context.SetContextObject(buildMapContext);
|
|
|
|
|
|
SetupBuildMap(buildMapContext, buildParametersContext);
|
|
|
|
|
|
|
|
|
|
|
|
// 检测构建结果
|
|
|
|
|
|
CheckBuildMapContent(buildMapContext);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 组织构建的资源包
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SetupBuildMap(BuildMapContext buildMapContext, AssetBundleBuilder.BuildParametersContext buildParameters)
|
|
|
|
|
|
{
|
2022-03-16 17:35:21 +08:00
|
|
|
|
Dictionary<string, BuildAssetInfo> buildAssetDic = new Dictionary<string, BuildAssetInfo>();
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 1. 获取主动收集的资源
|
2022-03-16 11:33:45 +08:00
|
|
|
|
List<CollectAssetInfo> allCollectInfos = AssetBundleCollectorSettingData.GetAllCollectAssets();
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 2. 对收集的资源进行依赖分析
|
|
|
|
|
|
int progressValue = 0;
|
2022-03-16 11:33:45 +08:00
|
|
|
|
foreach (CollectAssetInfo collectInfo in allCollectInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
string mainAssetPath = collectInfo.AssetPath;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取所有依赖资源
|
|
|
|
|
|
List<BuildAssetInfo> depends = GetAllDependencies(mainAssetPath);
|
|
|
|
|
|
for (int i = 0; i < depends.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
string assetPath = depends[i].AssetPath;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果已经存在,则增加该资源的依赖计数
|
2022-03-16 17:35:21 +08:00
|
|
|
|
if (buildAssetDic.ContainsKey(assetPath))
|
|
|
|
|
|
buildAssetDic[assetPath].DependCount++;
|
2022-03-01 10:44:12 +08:00
|
|
|
|
else
|
2022-03-16 17:35:21 +08:00
|
|
|
|
buildAssetDic.Add(assetPath, depends[i]);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加资源标记
|
2022-03-16 17:35:21 +08:00
|
|
|
|
buildAssetDic[assetPath].AddAssetTags(collectInfo.AssetTags);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 注意:检测是否为主动收集资源
|
|
|
|
|
|
if (assetPath == mainAssetPath)
|
|
|
|
|
|
{
|
2022-03-16 17:35:21 +08:00
|
|
|
|
buildAssetDic[mainAssetPath].IsCollectAsset = true;
|
|
|
|
|
|
buildAssetDic[mainAssetPath].IsRawAsset = collectInfo.IsRawAsset;
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加所有的依赖资源列表
|
|
|
|
|
|
// 注意:不包括自己
|
|
|
|
|
|
var allDependAssetInfos = new List<BuildAssetInfo>(depends.Count);
|
|
|
|
|
|
for (int i = 0; i < depends.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
string assetPath = depends[i].AssetPath;
|
|
|
|
|
|
if (assetPath != mainAssetPath)
|
2022-03-16 17:35:21 +08:00
|
|
|
|
allDependAssetInfos.Add(buildAssetDic[assetPath]);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
2022-03-16 17:35:21 +08:00
|
|
|
|
buildAssetDic[mainAssetPath].SetAllDependAssetInfos(allDependAssetInfos);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
EditorTools.DisplayProgressBar("依赖文件分析", ++progressValue, allCollectInfos.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
EditorTools.ClearProgressBar();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 移除零依赖的资源
|
|
|
|
|
|
var redundancy = CreateAssetRedundancy();
|
|
|
|
|
|
List<BuildAssetInfo> undependentAssets = new List<BuildAssetInfo>();
|
2022-03-16 17:35:21 +08:00
|
|
|
|
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
var buildAssetInfo = pair.Value;
|
|
|
|
|
|
if (buildAssetInfo.IsCollectAsset)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if (buildAssetInfo.DependCount == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
undependentAssets.Add(buildAssetInfo);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 冗余扩展
|
|
|
|
|
|
if(redundancy != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(redundancy.Check(buildAssetInfo.AssetPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
undependentAssets.Add(buildAssetInfo);
|
2022-03-16 22:25:55 +08:00
|
|
|
|
buildMapContext.RedundancyList.Add(buildAssetInfo.AssetPath);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 冗余机制
|
|
|
|
|
|
if (buildParameters.Parameters.ApplyRedundancy)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (AssetBundleCollectorSettingData.HasCollector(buildAssetInfo.AssetPath) == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
undependentAssets.Add(buildAssetInfo);
|
2022-03-16 22:25:55 +08:00
|
|
|
|
buildMapContext.RedundancyList.Add(buildAssetInfo.AssetPath);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (var assetInfo in undependentAssets)
|
|
|
|
|
|
{
|
2022-03-16 17:35:21 +08:00
|
|
|
|
buildAssetDic.Remove(assetInfo.AssetPath);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 设置资源包名
|
|
|
|
|
|
progressValue = 0;
|
2022-03-16 17:35:21 +08:00
|
|
|
|
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
var assetInfo = pair.Value;
|
|
|
|
|
|
var bundleLabel = AssetBundleCollectorSettingData.GetBundleLabel(assetInfo.AssetPath);
|
|
|
|
|
|
if (assetInfo.IsRawAsset)
|
|
|
|
|
|
assetInfo.SetBundleLabelAndVariant(bundleLabel, ResourceSettingData.Setting.RawFileVariant);
|
|
|
|
|
|
else
|
|
|
|
|
|
assetInfo.SetBundleLabelAndVariant(bundleLabel, ResourceSettingData.Setting.AssetBundleFileVariant);
|
2022-03-16 17:35:21 +08:00
|
|
|
|
EditorTools.DisplayProgressBar("设置资源包名", ++progressValue, buildAssetDic.Count);
|
2022-03-01 10:44:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
EditorTools.ClearProgressBar();
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 构建资源包
|
2022-03-16 17:35:21 +08:00
|
|
|
|
var allAssets = buildAssetDic.Values.ToList();
|
2022-03-01 10:44:12 +08:00
|
|
|
|
if (allAssets.Count == 0)
|
|
|
|
|
|
throw new Exception("构建的资源列表不能为空");
|
|
|
|
|
|
foreach (var assetInfo in allAssets)
|
|
|
|
|
|
{
|
|
|
|
|
|
buildMapContext.PackAsset(assetInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取指定资源依赖的所有资源列表
|
|
|
|
|
|
/// 注意:返回列表里已经包括主资源自己
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private List<BuildAssetInfo> GetAllDependencies(string mainAssetPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<BuildAssetInfo> result = new List<BuildAssetInfo>();
|
|
|
|
|
|
string[] depends = AssetDatabase.GetDependencies(mainAssetPath, true);
|
|
|
|
|
|
foreach (string assetPath in depends)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (AssetBundleCollectorSettingData.IsValidateAsset(assetPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
BuildAssetInfo assetInfo = new BuildAssetInfo(assetPath);
|
|
|
|
|
|
result.Add(assetInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检测构建结果
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void CheckBuildMapContent(BuildMapContext buildMapContext)
|
|
|
|
|
|
{
|
2022-03-16 22:25:55 +08:00
|
|
|
|
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
2022-03-01 10:44:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 注意:原生文件资源包只能包含一个原生文件
|
|
|
|
|
|
bool isRawFile = bundleInfo.IsRawFile;
|
|
|
|
|
|
if (isRawFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bundleInfo.Assets.Count != 1)
|
|
|
|
|
|
throw new Exception("The bundle does not support multiple raw asset : {bundleInfo.BundleName}");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 注意:原生文件不能被其它资源文件依赖
|
|
|
|
|
|
foreach (var assetInfo in bundleInfo.Assets)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (assetInfo.AllDependAssetInfos != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dependAssetInfo.IsRawAsset)
|
|
|
|
|
|
throw new Exception($"{assetInfo.AssetPath} can not depend raw asset : {dependAssetInfo.AssetPath}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建冗余类
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>如果没有定义类型,则返回NULL</returns>
|
|
|
|
|
|
private IAssetRedundancy CreateAssetRedundancy()
|
|
|
|
|
|
{
|
|
|
|
|
|
var types = AssemblyUtility.GetAssignableTypes(AssemblyUtility.UnityDefaultAssemblyEditorName, typeof(IAssetRedundancy));
|
|
|
|
|
|
if (types.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
if (types.Count != 1)
|
|
|
|
|
|
throw new Exception($"Found more {nameof(IAssetRedundancy)} types. We only support one.");
|
|
|
|
|
|
|
|
|
|
|
|
UnityEngine.Debug.Log($"创建实例类 : {types[0].FullName}");
|
|
|
|
|
|
return (IAssetRedundancy)Activator.CreateInstance(types[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|