123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor;
- using UnityEngine;
- namespace YooAsset.Editor
- {
- [Serializable]
- public class AssetBundleCollector
- {
- /// <summary>
- /// 收集路径
- /// 注意:支持文件夹或单个资源文件
- /// </summary>
- public string CollectPath = string.Empty;
- /// <summary>
- /// 收集器的GUID
- /// </summary>
- public string CollectorGUID = string.Empty;
- /// <summary>
- /// 收集器类型
- /// </summary>
- public ECollectorType CollectorType = ECollectorType.MainAssetCollector;
- /// <summary>
- /// 寻址规则类名
- /// </summary>
- public string AddressRuleName = nameof(AddressByFileName);
- /// <summary>
- /// 打包规则类名
- /// </summary>
- public string PackRuleName = nameof(PackDirectory);
- /// <summary>
- /// 过滤规则类名
- /// </summary>
- public string FilterRuleName = nameof(CollectAll);
- /// <summary>
- /// 资源分类标签
- /// </summary>
- public string AssetTags = string.Empty;
- /// <summary>
- /// 用户自定义数据
- /// </summary>
- public string UserData = string.Empty;
- /// <summary>
- /// 收集器是否有效
- /// </summary>
- public bool IsValid()
- {
- if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(CollectPath) == null)
- return false;
- if (CollectorType == ECollectorType.None)
- return false;
- if (AssetBundleCollectorSettingData.HasAddressRuleName(AddressRuleName) == false)
- return false;
- if (AssetBundleCollectorSettingData.HasPackRuleName(PackRuleName) == false)
- return false;
- if (AssetBundleCollectorSettingData.HasFilterRuleName(FilterRuleName) == false)
- return false;
- return true;
- }
- /// <summary>
- /// 检测配置错误
- /// </summary>
- public void CheckConfigError()
- {
- string assetGUID = AssetDatabase.AssetPathToGUID(CollectPath);
- if (string.IsNullOrEmpty(assetGUID))
- throw new Exception($"Invalid collect path : {CollectPath}");
- if (CollectorType == ECollectorType.None)
- throw new Exception($"{nameof(ECollectorType)}.{ECollectorType.None} is invalid in collector : {CollectPath}");
- if (AssetBundleCollectorSettingData.HasPackRuleName(PackRuleName) == false)
- throw new Exception($"Invalid {nameof(IPackRule)} class type : {PackRuleName} in collector : {CollectPath}");
- if (AssetBundleCollectorSettingData.HasFilterRuleName(FilterRuleName) == false)
- throw new Exception($"Invalid {nameof(IFilterRule)} class type : {FilterRuleName} in collector : {CollectPath}");
- if (AssetBundleCollectorSettingData.HasAddressRuleName(AddressRuleName) == false)
- throw new Exception($"Invalid {nameof(IAddressRule)} class type : {AddressRuleName} in collector : {CollectPath}");
- }
- /// <summary>
- /// 修复配置错误
- /// </summary>
- public bool FixConfigError()
- {
- bool isFixed = false;
- if (string.IsNullOrEmpty(CollectorGUID) == false)
- {
- string convertAssetPath = AssetDatabase.GUIDToAssetPath(CollectorGUID);
- if (string.IsNullOrEmpty(convertAssetPath))
- {
- Debug.LogWarning($"Collector GUID {CollectorGUID} is invalid and has been auto removed !");
- CollectorGUID = string.Empty;
- isFixed = true;
- }
- else
- {
- if (CollectPath != convertAssetPath)
- {
- CollectPath = convertAssetPath;
- isFixed = true;
- Debug.LogWarning($"Fix collect path : {CollectPath} -> {convertAssetPath}");
- }
- }
- }
- /*
- string convertGUID = AssetDatabase.AssetPathToGUID(CollectPath);
- if(string.IsNullOrEmpty(convertGUID) == false)
- {
- CollectorGUID = convertGUID;
- }
- */
- return isFixed;
- }
- /// <summary>
- /// 获取打包收集的资源文件
- /// </summary>
- public List<CollectAssetInfo> GetAllCollectAssets(CollectCommand command, AssetBundleCollectorGroup group)
- {
- // 注意:模拟构建模式下只收集主资源
- if (command.BuildMode == EBuildMode.SimulateBuild)
- {
- if (CollectorType != ECollectorType.MainAssetCollector)
- return new List<CollectAssetInfo>();
- }
- Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(1000);
- // 检测是否为原生资源打包规则
- IPackRule packRuleInstance = AssetBundleCollectorSettingData.GetPackRuleInstance(PackRuleName);
- bool isRawFilePackRule = packRuleInstance.IsRawFilePackRule();
- // 检测原生资源包的收集器类型
- if (isRawFilePackRule && CollectorType != ECollectorType.MainAssetCollector)
- throw new Exception($"The raw file pack rule must be set to {nameof(ECollectorType)}.{ECollectorType.MainAssetCollector} : {CollectPath}");
- if (string.IsNullOrEmpty(CollectPath))
- throw new Exception($"The collect path is null or empty in group : {group.GroupName}");
- // 收集打包资源
- if (AssetDatabase.IsValidFolder(CollectPath))
- {
- string collectDirectory = CollectPath;
- string[] findAssets = EditorTools.FindAssets(EAssetSearchType.All, collectDirectory);
- foreach (string assetPath in findAssets)
- {
- if (IsValidateAsset(assetPath, isRawFilePackRule) && IsCollectAsset(assetPath))
- {
- if (result.ContainsKey(assetPath) == false)
- {
- var collectAssetInfo = CreateCollectAssetInfo(command, group, assetPath, isRawFilePackRule);
- result.Add(assetPath, collectAssetInfo);
- }
- else
- {
- throw new Exception($"The collecting asset file is existed : {assetPath} in collector : {CollectPath}");
- }
- }
- }
- }
- else
- {
- string assetPath = CollectPath;
- if (IsValidateAsset(assetPath, isRawFilePackRule) && IsCollectAsset(assetPath))
- {
- var collectAssetInfo = CreateCollectAssetInfo(command, group, assetPath, isRawFilePackRule);
- result.Add(assetPath, collectAssetInfo);
- }
- else
- {
- throw new Exception($"The collecting single asset file is invalid : {assetPath} in collector : {CollectPath}");
- }
- }
- // 检测可寻址地址是否重复
- if (command.EnableAddressable)
- {
- var addressTemper = new Dictionary<string, string>();
- foreach (var collectInfoPair in result)
- {
- if (collectInfoPair.Value.CollectorType == ECollectorType.MainAssetCollector)
- {
- string address = collectInfoPair.Value.Address;
- string assetPath = collectInfoPair.Value.AssetPath;
- if (address.StartsWith("Assets/") || address.StartsWith("assets/"))
- throw new Exception($"The address can not set asset path in collector : {CollectPath} \nAssetPath: {assetPath}");
- if (addressTemper.TryGetValue(address, out var existed) == false)
- addressTemper.Add(address, assetPath);
- else
- throw new Exception($"The address is existed : {address} in collector : {CollectPath} \nAssetPath:\n {existed}\n {assetPath}");
- }
- }
- }
- // 返回列表
- return result.Values.ToList();
- }
- private CollectAssetInfo CreateCollectAssetInfo(CollectCommand command, AssetBundleCollectorGroup group, string assetPath, bool isRawFilePackRule)
- {
- string address = GetAddress(command, group, assetPath);
- string bundleName = GetBundleName(command, group, assetPath);
- List<string> assetTags = GetAssetTags(group);
- CollectAssetInfo collectAssetInfo = new CollectAssetInfo(CollectorType, bundleName, address, assetPath, isRawFilePackRule, assetTags);
- // 注意:模拟构建模式下不需要收集依赖资源
- if (command.BuildMode == EBuildMode.SimulateBuild)
- collectAssetInfo.DependAssets = new List<string>();
- else
- collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
- return collectAssetInfo;
- }
- private bool IsValidateAsset(string assetPath, bool isRawFilePackRule)
- {
- if (assetPath.StartsWith("Assets/") == false && assetPath.StartsWith("Packages/") == false)
- {
- UnityEngine.Debug.LogError($"Invalid asset path : {assetPath}");
- return false;
- }
- // 忽略文件夹
- if (AssetDatabase.IsValidFolder(assetPath))
- return false;
- // 忽略编辑器下的类型资源
- Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
- if (assetType == typeof(LightingDataAsset))
- return false;
- // 检测原生文件是否合规
- if (isRawFilePackRule)
- {
- string extension = EditorTools.RemoveFirstChar(System.IO.Path.GetExtension(assetPath));
- if (extension == EAssetFileExtension.unity.ToString() || extension == EAssetFileExtension.prefab.ToString() ||
- extension == EAssetFileExtension.fbx.ToString() || extension == EAssetFileExtension.mat.ToString() ||
- extension == EAssetFileExtension.controller.ToString() || extension == EAssetFileExtension.anim.ToString() ||
- extension == EAssetFileExtension.ttf.ToString() || extension == EAssetFileExtension.shader.ToString())
- {
- UnityEngine.Debug.LogWarning($"Raw file pack rule can not support file estension : {extension}");
- return false;
- }
- // 注意:原生文件只支持无依赖关系的资源
- /*
- string[] depends = AssetDatabase.GetDependencies(assetPath, true);
- if (depends.Length != 1)
- {
- UnityEngine.Debug.LogWarning($"Raw file pack rule can not support estension : {extension}");
- return false;
- }
- */
- }
- else
- {
- // 忽略Unity无法识别的无效文件
- // 注意:只对非原生文件收集器处理
- if (assetType == typeof(UnityEditor.DefaultAsset))
- {
- UnityEngine.Debug.LogWarning($"Cannot pack default asset : {assetPath}");
- return false;
- }
- }
- string fileExtension = System.IO.Path.GetExtension(assetPath);
- if (DefaultFilterRule.IsIgnoreFile(fileExtension))
- return false;
- return true;
- }
- private bool IsCollectAsset(string assetPath)
- {
- // 根据规则设置过滤资源文件
- IFilterRule filterRuleInstance = AssetBundleCollectorSettingData.GetFilterRuleInstance(FilterRuleName);
- return filterRuleInstance.IsCollectAsset(new FilterRuleData(assetPath));
- }
- private string GetAddress(CollectCommand command, AssetBundleCollectorGroup group, string assetPath)
- {
- if (command.EnableAddressable == false)
- return string.Empty;
- if (CollectorType != ECollectorType.MainAssetCollector)
- return string.Empty;
- IAddressRule addressRuleInstance = AssetBundleCollectorSettingData.GetAddressRuleInstance(AddressRuleName);
- string adressValue = addressRuleInstance.GetAssetAddress(new AddressRuleData(assetPath, CollectPath, group.GroupName, UserData));
- return adressValue;
- }
- private string GetBundleName(CollectCommand command, AssetBundleCollectorGroup group, string assetPath)
- {
- System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
- if (assetType == typeof(UnityEngine.Shader) || assetType == typeof(UnityEngine.ShaderVariantCollection))
- {
- // 获取着色器打包规则结果
- PackRuleResult packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
- return packRuleResult.GetMainBundleName(command.PackageName, command.UniqueBundleName);
- }
- else
- {
- // 获取其它资源打包规则结果
- IPackRule packRuleInstance = AssetBundleCollectorSettingData.GetPackRuleInstance(PackRuleName);
- PackRuleResult packRuleResult = packRuleInstance.GetPackRuleResult(new PackRuleData(assetPath, CollectPath, group.GroupName, UserData));
- return packRuleResult.GetMainBundleName(command.PackageName, command.UniqueBundleName);
- }
- }
- private List<string> GetAssetTags(AssetBundleCollectorGroup group)
- {
- List<string> tags = EditorTools.StringToStringList(group.AssetTags, ';');
- List<string> temper = EditorTools.StringToStringList(AssetTags, ';');
- tags.AddRange(temper);
- return tags;
- }
- private List<string> GetAllDependencies(string mainAssetPath)
- {
- string[] depends = AssetDatabase.GetDependencies(mainAssetPath, true);
- List<string> result = new List<string>(depends.Length);
- foreach (string assetPath in depends)
- {
- // 注意:排除主资源对象
- if (assetPath == mainAssetPath)
- continue;
- if (IsValidateAsset(assetPath, false))
- {
- result.Add(assetPath);
- }
- }
- return result;
- }
- }
- }
|