Optimize packaging bundle core logic

优化了打包的核心逻辑,对依赖资源进行自动划分。
This commit is contained in:
hevinci
2022-04-30 19:10:52 +08:00
parent b1bb79bd95
commit b443a1c308
17 changed files with 308 additions and 278 deletions
@@ -1,15 +1,20 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace YooAsset.Editor
{
public class BuildAssetInfo
{
private string _mainBundleName;
private string _shareBundleName;
private readonly HashSet<string> _dependBundleNames = new HashSet<string>();
/// <summary>
/// 资源包名称
/// 收集器类型
/// </summary>
public string BundleName { private set; get; }
public ECollectorType CollectorType { private set; get; }
/// <summary>
/// 可寻址地址
@@ -26,26 +31,11 @@ namespace YooAsset.Editor
/// </summary>
public bool IsRawAsset { private set; get; }
/// <summary>
/// 不写入资源列表
/// </summary>
public bool NotWriteToAssetList { private set; get; }
/// <summary>
/// 是否为主动收集资源
/// </summary>
public bool IsCollectAsset { private set; get; }
/// <summary>
/// 是否为着色器资源
/// </summary>
public bool IsShaderAsset { private set; get; }
/// <summary>
/// 被依赖次数
/// </summary>
public int DependCount = 0;
/// <summary>
/// 资源分类标签列表
/// </summary>
@@ -58,13 +48,13 @@ namespace YooAsset.Editor
public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }
public BuildAssetInfo(string address, string assetPath, bool isRawAsset, bool notWriteToAssetList)
public BuildAssetInfo(ECollectorType collectorType, string mainBundleName, string address, string assetPath, bool isRawAsset)
{
_mainBundleName = mainBundleName;
CollectorType = collectorType;
Address = address;
AssetPath = assetPath;
IsRawAsset = isRawAsset;
NotWriteToAssetList = notWriteToAssetList;
IsCollectAsset = true;
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
@@ -72,12 +62,12 @@ namespace YooAsset.Editor
else
IsShaderAsset = false;
}
public BuildAssetInfo(string assetPath)
public BuildAssetInfo(ECollectorType collectorType, string assetPath)
{
CollectorType = collectorType;
Address = string.Empty;
AssetPath = assetPath;
IsRawAsset = false;
NotWriteToAssetList = true;
IsCollectAsset = false;
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
@@ -86,6 +76,7 @@ namespace YooAsset.Editor
IsShaderAsset = false;
}
/// <summary>
/// 设置所有依赖的资源
/// </summary>
@@ -97,17 +88,6 @@ namespace YooAsset.Editor
AllDependAssetInfos = dependAssetInfos;
}
/// <summary>
/// 设置资源包名称
/// </summary>
public void SetBundleName(string bundleName)
{
if (string.IsNullOrEmpty(BundleName) == false)
throw new System.Exception("Should never get here !");
BundleName = bundleName;
}
/// <summary>
/// 添加资源分类标签
/// </summary>
@@ -115,30 +95,91 @@ namespace YooAsset.Editor
{
foreach (var tag in tags)
{
AddAssetTag(tag);
if (AssetTags.Contains(tag) == false)
{
AssetTags.Add(tag);
}
}
}
/// <summary>
/// 添加资源分类标签
/// 资源包名是否存在
/// </summary>
public void AddAssetTag(string tag)
public bool HasBundleName()
{
if (AssetTags.Contains(tag) == false)
{
AssetTags.Add(tag);
}
}
/// <summary>
/// 资源包名称是否有效
/// </summary>
public bool BundleNameIsValid()
{
if (string.IsNullOrEmpty(BundleName))
string bundleName = GetBundleName();
if (string.IsNullOrEmpty(bundleName))
return false;
else
return true;
}
/// <summary>
/// 获取资源包名称
/// </summary>
public string GetBundleName()
{
if (CollectorType == ECollectorType.None)
return _shareBundleName;
else
return _mainBundleName;
}
/// <summary>
/// 设置依赖资源包名称
/// </summary>
public void AddDependBundleName(string bundleName)
{
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
if (_dependBundleNames.Contains(bundleName) == false)
_dependBundleNames.Add(bundleName);
}
/// <summary>
/// 计算主资源或共享资源的完整包名
/// </summary>
public void CalculateFullBundleName()
{
if (CollectorType == ECollectorType.None)
{
if (IsRawAsset)
throw new Exception("Should never get here !");
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
if (IsShaderAsset)
{
string shareBundleName = $"{AssetBundleGrouperSettingData.Setting.ShadersBundleName}.{YooAssetSettingsData.Setting.AssetBundleFileVariant}";
_shareBundleName = EditorTools.GetRegularPath(shareBundleName).ToLower();
return;
}
}
if (_dependBundleNames.Count > 1)
{
var bundleNameList = _dependBundleNames.ToList();
bundleNameList.Sort();
string combineName = string.Join("|", bundleNameList);
var combineNameHash = HashUtility.StringSHA1(combineName);
var shareBundleName = $"share_{combineNameHash}.{YooAssetSettingsData.Setting.AssetBundleFileVariant}";
_shareBundleName = EditorTools.GetRegularPath(shareBundleName).ToLower();
}
}
else
{
if (IsRawAsset)
{
string mainBundleName = $"{_mainBundleName}.{YooAssetSettingsData.Setting.RawFileVariant}";
_mainBundleName = EditorTools.GetRegularPath(mainBundleName).ToLower();
}
else
{
string mainBundleName = $"{_mainBundleName}.{YooAssetSettingsData.Setting.AssetBundleFileVariant}";
_mainBundleName = EditorTools.GetRegularPath(mainBundleName).ToLower(); ;
}
}
}
}
}
@@ -105,7 +105,7 @@ namespace YooAsset.Editor
/// </summary>
public BuildAssetInfo[] GetAllPatchAssetInfos()
{
return BuildinAssets.Where(t => t.IsCollectAsset && t.NotWriteToAssetList == false).ToArray();
return BuildinAssets.Where(t => t.CollectorType == ECollectorType.MainCollector).ToArray();
}
/// <summary>
@@ -25,13 +25,17 @@ namespace YooAsset.Editor
/// </summary>
public void PackAsset(BuildAssetInfo assetInfo)
{
if (TryGetBundleInfo(assetInfo.BundleName, out BuildBundleInfo bundleInfo))
string bundleName = assetInfo.GetBundleName();
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
if (TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo))
{
bundleInfo.PackAsset(assetInfo);
}
else
{
BuildBundleInfo newBundleInfo = new BuildBundleInfo(assetInfo.BundleName);
BuildBundleInfo newBundleInfo = new BuildBundleInfo(bundleName);
newBundleInfo.PackAsset(assetInfo);
BundleInfos.Add(newBundleInfo);
}
@@ -13,21 +13,20 @@ namespace YooAsset.Editor
public static BuildMapContext SetupBuildMap()
{
BuildMapContext context = new BuildMapContext();
Dictionary<string, BuildAssetInfo> buildAssetDic = new Dictionary<string, BuildAssetInfo>();
Dictionary<string, BuildAssetInfo> buildAssetDic = new Dictionary<string, BuildAssetInfo>(1000);
// 0. 检测配置合法性
// 1. 检测配置合法性
AssetBundleGrouperSettingData.Setting.CheckConfigError();
// 1. 获取主动收集的资源
List<CollectAssetInfo> collectAssetInfos = AssetBundleGrouperSettingData.Setting.GetAllCollectAssets();
// 2. 获取所有主动收集的资源
List<CollectAssetInfo> allCollectAssets = AssetBundleGrouperSettingData.Setting.GetAllCollectAssets();
// 2. 录入主动收集的资源
foreach (var collectAssetInfo in collectAssetInfos)
// 3. 录入主动收集的资源
foreach (var collectAssetInfo in allCollectAssets)
{
if (buildAssetDic.ContainsKey(collectAssetInfo.AssetPath) == false)
{
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.Address, collectAssetInfo.AssetPath, collectAssetInfo.IsRawAsset, collectAssetInfo.NotWriteToAssetList);
buildAssetInfo.SetBundleName(collectAssetInfo.BundleName);
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.CollectorType, collectAssetInfo.BundleName, collectAssetInfo.Address, collectAssetInfo.AssetPath, collectAssetInfo.IsRawAsset);
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
buildAssetDic.Add(collectAssetInfo.AssetPath, buildAssetInfo);
}
@@ -37,28 +36,29 @@ namespace YooAsset.Editor
}
}
// 3. 录入并分析依赖资源
foreach (var collectAssetInfo in collectAssetInfos)
// 4. 录入相关依赖的资源
foreach (var collectAssetInfo in allCollectAssets)
{
foreach (var dependAssetPath in collectAssetInfo.DependAssets)
{
if (buildAssetDic.ContainsKey(dependAssetPath))
{
buildAssetDic[dependAssetPath].DependCount++;
buildAssetDic[dependAssetPath].AddAssetTags(collectAssetInfo.AssetTags);
buildAssetDic[dependAssetPath].AddDependBundleName(collectAssetInfo.BundleName);
}
else
{
var buildAssetInfo = new BuildAssetInfo(dependAssetPath);
var buildAssetInfo = new BuildAssetInfo(ECollectorType.None, dependAssetPath);
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
buildAssetInfo.AddDependBundleName(collectAssetInfo.BundleName);
buildAssetDic.Add(dependAssetPath, buildAssetInfo);
}
}
}
context.AssetFileCount = buildAssetDic.Count;
// 4. 设置主动收集资源的依赖列表
foreach (var collectAssetInfo in collectAssetInfos)
// 5. 填充主动收集资源的依赖列表
foreach (var collectAssetInfo in allCollectAssets)
{
var dependAssetInfos = new List<BuildAssetInfo>(collectAssetInfo.DependAssets.Count);
foreach (var dependAssetPath in collectAssetInfo.DependAssets)
@@ -71,21 +71,18 @@ namespace YooAsset.Editor
buildAssetDic[collectAssetInfo.AssetPath].SetAllDependAssetInfos(dependAssetInfos);
}
// 5. 移除零依赖的资源
// 6. 计算完整的资源包名
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
{
pair.Value.CalculateFullBundleName();
}
// 7. 移除未参与构建的资源
List<BuildAssetInfo> removeList = new List<BuildAssetInfo>();
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
{
var buildAssetInfo = pair.Value;
if (buildAssetInfo.IsCollectAsset)
continue;
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
if (buildAssetInfo.IsShaderAsset)
continue;
}
if (buildAssetInfo.DependCount == 0)
if (buildAssetInfo.HasBundleName() == false)
removeList.Add(buildAssetInfo);
}
foreach (var removeValue in removeList)
@@ -93,32 +90,11 @@ namespace YooAsset.Editor
buildAssetDic.Remove(removeValue.AssetPath);
}
// 6. 设置未命名的资源包
IPackRule defaultPackRule = new PackDirectory();
foreach (KeyValuePair<string, BuildAssetInfo> pair in buildAssetDic)
{
var buildAssetInfo = pair.Value;
if (buildAssetInfo.BundleNameIsValid() == false)
{
string shaderBundleName = AssetBundleGrouperHelper.CollectShaderBundleName(buildAssetInfo.AssetPath);
if (string.IsNullOrEmpty(shaderBundleName) == false)
{
buildAssetInfo.SetBundleName(shaderBundleName);
}
else
{
string bundleName = defaultPackRule.GetBundleName(new PackRuleData(buildAssetInfo.AssetPath));
bundleName = AssetBundleGrouperHelper.CorrectBundleName(bundleName, false);
buildAssetInfo.SetBundleName(bundleName);
}
}
}
// 7. 构建资源包
var allBuildAssets = buildAssetDic.Values.ToList();
if (allBuildAssets.Count == 0)
// 8. 构建资源包
var allBuildinAssets = buildAssetDic.Values.ToList();
if (allBuildinAssets.Count == 0)
throw new Exception("构建的资源列表不能为空");
foreach (var assetInfo in allBuildAssets)
foreach (var assetInfo in allBuildinAssets)
{
context.PackAsset(assetInfo);
}
@@ -29,7 +29,7 @@ namespace YooAsset.Editor
catch (Exception e)
{
Debug.LogError($"Build task {task.GetType().Name} failed !");
Debug.LogError($"Detail error : {e}");
Debug.LogError($"Build error : {e}");
succeed = false;
break;
}
@@ -142,7 +142,7 @@ namespace YooAsset.Editor
else
patchAsset.Address = string.Empty;
patchAsset.AssetPath = assetInfo.AssetPath;
patchAsset.BundleID = GetAssetBundleID(assetInfo.BundleName, patchManifest);
patchAsset.BundleID = GetAssetBundleID(assetInfo.GetBundleName(), patchManifest);
patchAsset.DependIDs = GetAssetBundleDependIDs(patchAsset.BundleID, assetInfo, patchManifest);
result.Add(patchAsset);
}
@@ -154,13 +154,14 @@ namespace YooAsset.Editor
List<int> result = new List<int>();
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
{
if (dependAssetInfo.BundleNameIsValid() == false)
continue;
int bundleID = GetAssetBundleID(dependAssetInfo.BundleName, patchManifest);
if (mainBundleID != bundleID)
if (dependAssetInfo.HasBundleName())
{
if (result.Contains(bundleID) == false)
result.Add(bundleID);
int bundleID = GetAssetBundleID(dependAssetInfo.GetBundleName(), patchManifest);
if (mainBundleID != bundleID)
{
if (result.Contains(bundleID) == false)
result.Add(bundleID);
}
}
}
return result.ToArray();