Optimize packaging bundle core logic

优化了打包的核心逻辑,对依赖资源进行自动划分。
pull/9/head
hevinci 2022-04-30 19:10:52 +08:00
parent b1bb79bd95
commit b443a1c308
17 changed files with 308 additions and 278 deletions

View File

@ -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(); ;
}
}
}
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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();

View File

@ -14,6 +14,11 @@ namespace YooAsset.Editor
/// </summary>
public string CollectPath = string.Empty;
/// <summary>
/// 收集器类型
/// </summary>
public ECollectorType CollectorType = ECollectorType.MainCollector;
/// <summary>
/// 寻址规则类名
/// </summary>
@ -29,12 +34,6 @@ namespace YooAsset.Editor
/// </summary>
public string FilterRuleName = nameof(CollectAll);
/// <summary>
/// 不写入资源列表
/// </summary>
public bool NotWriteToAssetList = false;
/// <summary>
/// 资源分类标签
/// </summary>
@ -65,14 +64,17 @@ namespace YooAsset.Editor
if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(CollectPath) == null)
throw new Exception($"Invalid collect path : {CollectPath}");
if (CollectorType == ECollectorType.None)
throw new Exception($"{nameof(ECollectorType)}.{ECollectorType.None} is invalid in collector : {CollectPath}");
if (AssetBundleGrouperSettingData.HasPackRuleName(PackRuleName) == false)
throw new Exception($"Invalid {nameof(IPackRule)} class type : {PackRuleName}");
throw new Exception($"Invalid {nameof(IPackRule)} class type : {PackRuleName} in collector : {CollectPath}");
if (AssetBundleGrouperSettingData.HasFilterRuleName(FilterRuleName) == false)
throw new Exception($"Invalid {nameof(IFilterRule)} class type : {FilterRuleName}");
throw new Exception($"Invalid {nameof(IFilterRule)} class type : {FilterRuleName} in collector : {CollectPath}");
if (AssetBundleGrouperSettingData.HasAddressRuleName(AddressRuleName) == false)
throw new Exception($"Invalid {nameof(IAddressRule)} class type : {AddressRuleName}");
throw new Exception($"Invalid {nameof(IAddressRule)} class type : {AddressRuleName} in collector : {CollectPath}");
}
/// <summary>
@ -80,70 +82,61 @@ namespace YooAsset.Editor
/// </summary>
public List<CollectAssetInfo> GetAllCollectAssets(AssetBundleGrouper grouper)
{
Dictionary<string, string> adressTemper = new Dictionary<string, string>(1000);
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(1000);
bool isRawAsset = PackRuleName == nameof(PackRawFile);
// 如果是文件夹
// 检测原生资源包的收集器类型
if (isRawAsset && CollectorType != ECollectorType.MainCollector)
throw new Exception($"The raw file must be set to {nameof(ECollectorType)}.{ECollectorType.MainCollector} : {CollectPath}");
// 收集打包资源
if (AssetDatabase.IsValidFolder(CollectPath))
{
string collectDirectory = CollectPath;
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.All, collectDirectory);
foreach (string assetPath in findAssets)
{
if (IsValidateAsset(assetPath) == false)
continue;
if (IsCollectAsset(assetPath) == false)
continue;
if (result.ContainsKey(assetPath) == false)
if (IsValidateAsset(assetPath) && IsCollectAsset(assetPath))
{
string address = GetAddress(grouper, assetPath);
string bundleName = GetBundleName(grouper, assetPath, isRawAsset);
List<string> assetTags = GetAssetTags(grouper);
var collectAssetInfo = new CollectAssetInfo(bundleName, address, assetPath, assetTags, isRawAsset, NotWriteToAssetList);
collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
result.Add(assetPath, collectAssetInfo);
}
else
{
throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
if (result.ContainsKey(assetPath) == false)
{
var collectAssetInfo = CreateCollectAssetInfo(grouper, assetPath, isRawAsset);
result.Add(assetPath, collectAssetInfo);
}
else
{
throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
}
}
}
}
else
{
string assetPath = CollectPath;
if (result.ContainsKey(assetPath) == false)
if (IsValidateAsset(assetPath) && IsCollectAsset(assetPath))
{
if (isRawAsset && NotWriteToAssetList)
UnityEngine.Debug.LogWarning($"Are you sure raw file are not write to asset list : {assetPath}");
string address = GetAddress(grouper, assetPath);
string bundleName = GetBundleName(grouper, assetPath, isRawAsset);
List<string> assetTags = GetAssetTags(grouper);
var collectAssetInfo = new CollectAssetInfo(bundleName, address, assetPath, assetTags, isRawAsset, NotWriteToAssetList);
collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
var collectAssetInfo = CreateCollectAssetInfo(grouper, assetPath, isRawAsset);
result.Add(assetPath, collectAssetInfo);
}
else
{
throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
throw new Exception($"The collecting single asset file is invalid : {assetPath} in collector : {CollectPath}");
}
}
// 检测可寻址地址是否重复
if (AssetBundleGrouperSettingData.Setting.EnableAddressable)
{
foreach (var collectInfo in result)
HashSet<string> adressTemper = new HashSet<string>();
foreach (var collectInfoPair in result)
{
string address = collectInfo.Value.Address;
if (adressTemper.ContainsKey(address) == false)
if (collectInfoPair.Value.CollectorType == ECollectorType.MainCollector)
{
adressTemper.Add(address, address);
}
else
{
throw new Exception($"The address is existed : {address} in collector : {CollectPath}");
string address = collectInfoPair.Value.Address;
if (adressTemper.Contains(address) == false)
adressTemper.Add(address);
else
throw new Exception($"The address is existed : {address} in collector : {CollectPath}");
}
}
}
@ -152,7 +145,15 @@ namespace YooAsset.Editor
return result.Values.ToList();
}
private CollectAssetInfo CreateCollectAssetInfo(AssetBundleGrouper grouper, string assetPath, bool isRawAsset)
{
string address = GetAddress(grouper, assetPath);
string bundleName = GetBundleName(grouper, assetPath);
List<string> assetTags = GetAssetTags(grouper);
CollectAssetInfo collectAssetInfo = new CollectAssetInfo(CollectorType, bundleName, address, assetPath, assetTags, isRawAsset);
collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
return collectAssetInfo;
}
private bool IsValidateAsset(string assetPath)
{
if (assetPath.StartsWith("Assets/") == false && assetPath.StartsWith("Packages/") == false)
@ -188,24 +189,31 @@ namespace YooAsset.Editor
}
private string GetAddress(AssetBundleGrouper grouper, string assetPath)
{
if (NotWriteToAssetList)
return assetPath;
if (CollectorType != ECollectorType.MainCollector)
return string.Empty;
IAddressRule addressRuleInstance = AssetBundleGrouperSettingData.GetAddressRuleInstance(AddressRuleName);
string adressValue = addressRuleInstance.GetAssetAddress(new AddressRuleData(assetPath, CollectPath, grouper.GrouperName));
return adressValue;
}
private string GetBundleName(AssetBundleGrouper grouper, string assetPath, bool isRawAsset)
private string GetBundleName(AssetBundleGrouper grouper, string assetPath)
{
string shaderBundleName = AssetBundleGrouperHelper.CollectShaderBundleName(assetPath);
if (string.IsNullOrEmpty(shaderBundleName) == false)
return shaderBundleName;
// 如果自动收集所有的着色器
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
{
string bundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
return EditorTools.GetRegularPath(bundleName).ToLower();
}
}
// 根据规则设置获取资源包名称
{
IPackRule packRuleInstance = AssetBundleGrouperSettingData.GetPackRuleInstance(PackRuleName);
string bundleName = packRuleInstance.GetBundleName(new PackRuleData(assetPath, CollectPath, grouper.GrouperName));
return AssetBundleGrouperHelper.CorrectBundleName(bundleName, isRawAsset);
return EditorTools.GetRegularPath(bundleName).ToLower();
}
}
private List<string> GetAssetTags(AssetBundleGrouper grouper)

View File

@ -47,41 +47,39 @@ namespace YooAsset.Editor
/// </summary>
public List<CollectAssetInfo> GetAllCollectAssets()
{
Dictionary<string, string> adressTemper = new Dictionary<string, string>(10000);
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000);
// 收集打包资源
foreach (var collector in Collectors)
{
var temper = collector.GetAllCollectAssets(this);
foreach (var assetInfo in temper)
{
if (result.ContainsKey(assetInfo.AssetPath) == false)
{
result.Add(assetInfo.AssetPath, assetInfo);
}
else
{
throw new Exception($"The collecting asset file is existed : {assetInfo.AssetPath} in grouper : {GrouperName}");
}
}
}
// 检测可寻址地址是否重复
if (AssetBundleGrouperSettingData.Setting.EnableAddressable)
{
foreach (var collectInfo in result)
HashSet<string> adressTemper = new HashSet<string>();
foreach (var collectInfoPair in result)
{
string address = collectInfo.Value.Address;
if (adressTemper.ContainsKey(address) == false)
if (collectInfoPair.Value.CollectorType == ECollectorType.MainCollector)
{
adressTemper.Add(address, address);
}
else
{
throw new Exception($"The address is existed : {address} in grouper : {GrouperName}");
string address = collectInfoPair.Value.Address;
if (adressTemper.Contains(address) == false)
adressTemper.Add(address);
else
throw new Exception($"The address is existed : {address} in grouper : {GrouperName}");
}
}
}
// 返回列表
return result.Values.ToList();
}
}

View File

@ -17,14 +17,13 @@ namespace YooAsset.Editor
public const string XmlGrouperName = "GrouperName";
public const string XmlGrouperDesc = "GrouperDesc";
public const string XmlCollector = "Collector";
public const string XmlDirectory = "CollectPath";
public const string XmlCollectPath = "CollectPath";
public const string XmlCollectorType = "CollectType";
public const string XmlAddressRule = "AddressRule";
public const string XmlPackRule = "PackRule";
public const string XmlFilterRule = "FilterRule";
public const string XmlNotWriteToAssetList = "NotWriteToAssetList";
public const string XmlAssetTags = "AssetTags";
/// <summary>
/// 导入XML配置表
/// </summary>
@ -81,25 +80,25 @@ namespace YooAsset.Editor
foreach (var collectorNode in collectorNodeList)
{
XmlElement collectorElement = collectorNode as XmlElement;
if (collectorElement.HasAttribute(XmlDirectory) == false)
throw new Exception($"Not found attribute {XmlDirectory} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlCollectPath) == false)
throw new Exception($"Not found attribute {XmlCollectPath} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlCollectorType) == false)
throw new Exception($"Not found attribute {XmlCollectorType} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlAddressRule) == false)
throw new Exception($"Not found attribute {XmlAddressRule} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlPackRule) == false)
throw new Exception($"Not found attribute {XmlPackRule} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlFilterRule) == false)
throw new Exception($"Not found attribute {XmlFilterRule} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlNotWriteToAssetList) == false)
throw new Exception($"Not found attribute {XmlNotWriteToAssetList} in {XmlCollector}");
if (collectorElement.HasAttribute(XmlAssetTags) == false)
throw new Exception($"Not found attribute {XmlAssetTags} in {XmlCollector}");
AssetBundleCollector collector = new AssetBundleCollector();
collector.CollectPath = collectorElement.GetAttribute(XmlDirectory);
collector.CollectPath = collectorElement.GetAttribute(XmlCollectPath);
collector.CollectorType = StringUtility.NameToEnum<ECollectorType>(collectorElement.GetAttribute(XmlCollectorType));
collector.AddressRuleName = collectorElement.GetAttribute(XmlAddressRule);
collector.PackRuleName = collectorElement.GetAttribute(XmlPackRule);
collector.FilterRuleName = collectorElement.GetAttribute(XmlFilterRule);
collector.NotWriteToAssetList = collectorElement.GetAttribute(XmlNotWriteToAssetList) == "True" ? true : false;
collector.AssetTags = collectorElement.GetAttribute(XmlAssetTags); ;
grouper.Collectors.Add(collector);
}
@ -149,11 +148,11 @@ namespace YooAsset.Editor
foreach (var collector in grouper.Collectors)
{
var collectorElement = xmlDoc.CreateElement(XmlCollector);
collectorElement.SetAttribute(XmlDirectory, collector.CollectPath);
collectorElement.SetAttribute(XmlCollectPath, collector.CollectPath);
collectorElement.SetAttribute(XmlCollectorType, collector.CollectorType.ToString());
collectorElement.SetAttribute(XmlAddressRule, collector.AddressRuleName);
collectorElement.SetAttribute(XmlPackRule, collector.PackRuleName);
collectorElement.SetAttribute(XmlFilterRule, collector.FilterRuleName);
collectorElement.SetAttribute(XmlNotWriteToAssetList, collector.NotWriteToAssetList.ToString());
collectorElement.SetAttribute(XmlAssetTags, collector.AssetTags);
grouperElement.AppendChild(collectorElement);
}

View File

@ -6,45 +6,11 @@ using UnityEditor;
namespace YooAsset.Editor
{
public static class AssetBundleGrouperHelper
/// <summary>
/// 编辑器下运行时支持
/// </summary>
public static class AssetBundleGrouperRuntimeSupport
{
/// <summary>
/// 收集着色器的资源包名称
/// </summary>
public static string CollectShaderBundleName(string assetPath)
{
// 如果自动收集所有的着色器
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
{
string bundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
return CorrectBundleName(bundleName, false);
}
}
return null;
}
/// <summary>
/// 修正资源包名称
/// </summary>
public static string CorrectBundleName(string bundleName, bool isRawBundle)
{
if (isRawBundle)
{
string fullName = $"{bundleName}.{YooAssetSettingsData.Setting.RawFileVariant}";
return EditorTools.GetRegularPath(fullName).ToLower();
}
else
{
string fullName = $"{bundleName}.{YooAssetSettingsData.Setting.AssetBundleFileVariant}";
return EditorTools.GetRegularPath(fullName).ToLower(); ;
}
}
#region 编辑器下运行时支持
private static readonly Dictionary<string, CollectAssetInfo> _locationDic = new Dictionary<string, CollectAssetInfo>(1000);
public static void InitEditorPlayMode(bool enableAddressable)
@ -56,7 +22,7 @@ namespace YooAsset.Editor
var collectAssetList = AssetBundleGrouperSettingData.Setting.GetAllCollectAssets();
foreach (var collectAsset in collectAssetList)
{
if (collectAsset.NotWriteToAssetList)
if(collectAsset.CollectorType != ECollectorType.MainCollector)
continue;
string address = collectAsset.Address;
@ -71,7 +37,7 @@ namespace YooAsset.Editor
var collectAssetList = AssetBundleGrouperSettingData.Setting.GetAllCollectAssets();
foreach (var collectAsset in collectAssetList)
{
if (collectAsset.NotWriteToAssetList)
if (collectAsset.CollectorType != ECollectorType.MainCollector)
continue;
// 添加原始路径
@ -128,6 +94,5 @@ namespace YooAsset.Editor
UnityEngine.Debug.LogWarning($"Found illegal character in location : \"{location}\"");
}
}
#endregion
}
}

View File

@ -45,41 +45,39 @@ namespace YooAsset.Editor
/// </summary>
public List<CollectAssetInfo> GetAllCollectAssets()
{
Dictionary<string, string> adressTemper = new Dictionary<string, string>(10000);
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000);
// 收集打包资源
foreach (var grouper in Groupers)
{
var temper = grouper.GetAllCollectAssets();
foreach (var assetInfo in temper)
{
if (result.ContainsKey(assetInfo.AssetPath) == false)
{
result.Add(assetInfo.AssetPath, assetInfo);
}
else
{
throw new Exception($"The collecting asset file is existed : {assetInfo.AssetPath}");
}
throw new Exception($"The collecting asset file is existed : {assetInfo.AssetPath} in grouper setting.");
}
}
// 检测可寻址地址是否重复
if (EnableAddressable)
{
foreach (var collectInfo in result)
HashSet<string> adressTemper = new HashSet<string>();
foreach (var collectInfoPair in result)
{
string address = collectInfo.Value.Address;
if (adressTemper.ContainsKey(address) == false)
if (collectInfoPair.Value.CollectorType == ECollectorType.MainCollector)
{
adressTemper.Add(address, address);
}
else
{
throw new Exception($"The address is existed : {address}");
string address = collectInfoPair.Value.Address;
if (adressTemper.Contains(address) == false)
adressTemper.Add(address);
else
throw new Exception($"The address is existed : {address} in grouper setting.");
}
}
}
// 返回列表
return result.Values.ToList();
}
}

View File

@ -18,6 +18,7 @@ namespace YooAsset.Editor
window.minSize = new Vector2(800, 600);
}
private List<string> _collectorTypeList;
private List<string> _addressRuleList;
private List<string> _packRuleList;
private List<string> _filterRuleList;
@ -38,6 +39,7 @@ namespace YooAsset.Editor
VisualElement root = this.rootVisualElement;
_collectorTypeList = new List<string>() { $"{nameof(ECollectorType.MainCollector)}", $"{nameof(ECollectorType.StaticCollector)}"};
_addressRuleList = AssetBundleGrouperSettingData.GetAddressRuleNames();
_packRuleList = AssetBundleGrouperSettingData.GetPackRuleNames();
_filterRuleList = AssetBundleGrouperSettingData.GetFilterRuleNames();
@ -318,6 +320,13 @@ namespace YooAsset.Editor
label.style.width = 90;
elementBottom.Add(label);
}
{
var popupField = new PopupField<string>(_collectorTypeList, 0);
popupField.name = "PopupField0";
popupField.style.unityTextAlign = TextAnchor.MiddleLeft;
popupField.style.width = 150;
elementBottom.Add(popupField);
}
if (_enableAddressableToogle.value)
{
var popupField = new PopupField<string>(_addressRuleList, 0);
@ -340,17 +349,6 @@ namespace YooAsset.Editor
popupField.style.width = 150;
elementBottom.Add(popupField);
}
{
var toggle = new Toggle();
toggle.name = "Toggle1";
toggle.label = "NotWriteToAssetList";
toggle.style.unityTextAlign = TextAnchor.MiddleLeft;
toggle.style.width = 150;
toggle.style.marginLeft = 20;
elementBottom.Add(toggle);
var label = toggle.Q<Label>();
label.style.minWidth = 130;
}
{
var textField = new TextField();
textField.name = "TextField1";
@ -408,7 +406,7 @@ namespace YooAsset.Editor
RemoveCollectorBtn_clicked(collector);
};
// Collect Path
// Collector Path
var objectField1 = element.Q<ObjectField>("ObjectField1");
objectField1.SetValueWithoutNotify(collectObject);
objectField1.RegisterValueChangedCallback(evt =>
@ -419,6 +417,16 @@ namespace YooAsset.Editor
RefreshFoldout(foldout, selectGrouper, collector);
});
// Collector Type
var popupField0 = element.Q<PopupField<string>>("PopupField0");
popupField0.index = GetCollectorTypeIndex(collector.CollectorType.ToString());
popupField0.RegisterValueChangedCallback(evt =>
{
collector.CollectorType = StringUtility.NameToEnum<ECollectorType>(evt.newValue);
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
RefreshFoldout(foldout, selectGrouper, collector);
});
// Address Rule
var popupField1 = element.Q<PopupField<string>>("PopupField1");
if (popupField1 != null)
@ -452,16 +460,6 @@ namespace YooAsset.Editor
RefreshFoldout(foldout, selectGrouper, collector);
});
// NotWriteToAssetList
var toggle1 = element.Q<Toggle>("Toggle1");
toggle1.SetValueWithoutNotify(collector.NotWriteToAssetList);
toggle1.RegisterValueChangedCallback(evt =>
{
collector.NotWriteToAssetList = evt.newValue;
AssetBundleGrouperSettingData.ModifyCollector(selectGrouper, collector);
RefreshFoldout(foldout, selectGrouper, collector);
});
// Tags
var textFiled1 = element.Q<TextField>("TextField1");
textFiled1.SetValueWithoutNotify(collector.AssetTags);
@ -476,7 +474,7 @@ namespace YooAsset.Editor
// 清空旧元素
foldout.Clear();
if (collector.IsValid() && collector.NotWriteToAssetList == false)
if (collector.IsValid() && collector.CollectorType == ECollectorType.MainCollector)
{
List<CollectAssetInfo> collectAssetInfos = null;
@ -484,12 +482,12 @@ namespace YooAsset.Editor
{
collectAssetInfos = collector.GetAllCollectAssets(grouper);
}
catch(System.Exception e)
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
if(collectAssetInfos != null)
if (collectAssetInfos != null)
{
foreach (var collectAssetInfo in collectAssetInfos)
{
@ -536,6 +534,15 @@ namespace YooAsset.Editor
FillCollectorViewData();
}
private int GetCollectorTypeIndex(string typeName)
{
for (int i = 0; i < _collectorTypeList.Count; i++)
{
if (_collectorTypeList[i] == typeName)
return i;
}
return 0;
}
private int GetAddressRuleIndex(string ruleName)
{
for (int i = 0; i < _addressRuleList.Count; i++)

View File

@ -5,6 +5,11 @@ namespace YooAsset.Editor
{
public class CollectAssetInfo
{
/// <summary>
/// 收集器类型
/// </summary>
public ECollectorType CollectorType { private set; get; }
/// <summary>
/// 资源包名称
/// </summary>
@ -30,25 +35,20 @@ namespace YooAsset.Editor
/// </summary>
public bool IsRawAsset { private set; get; }
/// <summary>
/// 不写入资源列表
/// </summary>
public bool NotWriteToAssetList { private set; get; }
/// <summary>
/// 依赖的资源列表
/// </summary>
public List<string> DependAssets = new List<string>();
public CollectAssetInfo(string bundleName, string address, string assetPath, List<string> assetTags, bool isRawAsset, bool notWriteToAssetList)
public CollectAssetInfo(ECollectorType collectorType, string bundleName, string address, string assetPath, List<string> assetTags, bool isRawAsset)
{
CollectorType = collectorType;
BundleName = bundleName;
Address = address;
AssetPath = assetPath;
AssetTags = assetTags;
IsRawAsset = isRawAsset;
NotWriteToAssetList = notWriteToAssetList;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
namespace YooAsset.Editor
{
[Serializable]
public enum ECollectorType
{
/// <summary>
/// 收集参与打包构建的资源对象,并全部写入到资源清单的资源列表里(可以通过代码加载)。
/// </summary>
MainCollector,
/// <summary>
/// 收集参与打包构建的资源对象,但不写入到资源清单的资源列表里(无法通过代码加载)。
/// </summary>
StaticCollector,
/// <summary>
/// 该收集器类型不能被设置
/// </summary>
None,
}
}

View File

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

View File

@ -9,14 +9,13 @@ namespace YooAsset
public static void InitEditorPlayMode(bool enableAddressable)
{
AssetBundleGrouperSettingHelperClassType = Assembly.Load("YooAsset.Editor").GetType("YooAsset.Editor.AssetBundleGrouperHelper");
AssetBundleGrouperSettingHelperClassType = Assembly.Load("YooAsset.Editor").GetType("YooAsset.Editor.AssetBundleGrouperRuntimeSupport");
InvokePublicStaticMethod(AssetBundleGrouperSettingHelperClassType, "InitEditorPlayMode", enableAddressable);
}
public static string ConvertLocationToAssetPath(string location)
{
return (string)InvokePublicStaticMethod(AssetBundleGrouperSettingHelperClassType, "ConvertLocationToAssetPath", location);
}
private static object InvokePublicStaticMethod(System.Type type, string method, params object[] parameters)
{
var methodInfo = type.GetMethod(method, BindingFlags.Public | BindingFlags.Static);