123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- using System;
- using System.Linq;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEditor.Build.Pipeline;
- using UnityEditor.Build.Pipeline.Interfaces;
- namespace YooAsset.Editor
- {
- public class ManifestContext : IContextObject
- {
- internal PackageManifest Manifest;
- }
- [TaskAttribute("创建清单文件")]
- public class TaskCreateManifest : IBuildTask
- {
- void IBuildTask.Run(BuildContext context)
- {
- CreateManifestFile(context);
- }
- /// <summary>
- /// 创建补丁清单文件到输出目录
- /// </summary>
- private void CreateManifestFile(BuildContext context)
- {
- var buildMapContext = context.GetContextObject<BuildMapContext>();
- var buildParametersContext = context.GetContextObject<BuildParametersContext>();
- var buildParameters = buildParametersContext.Parameters;
- string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
- // 创建新补丁清单
- PackageManifest manifest = new PackageManifest();
- manifest.FileVersion = YooAssetSettings.ManifestFileVersion;
- manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
- manifest.LocationToLower = buildMapContext.Command.LocationToLower;
- manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
- manifest.OutputNameStyle = (int)buildParameters.OutputNameStyle;
- manifest.PackageName = buildParameters.PackageName;
- manifest.PackageVersion = buildParameters.PackageVersion;
- // 填充资源包集合
- manifest.BundleList = GetAllPackageBundle(context);
- CacheBundleIDs(manifest);
- // 填充主资源集合
- manifest.AssetList = GetAllPackageAsset(context, manifest);
- // 更新Unity内置资源包的引用关系
- if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
- {
- if (buildParameters.BuildMode == EBuildMode.IncrementalBuild)
- {
- var buildResultContext = context.GetContextObject<TaskBuilding_SBP.BuildResultContext>();
- UpdateBuiltInBundleReference(manifest, buildResultContext, buildMapContext.Command.ShadersBundleName);
- }
- }
- // 更新资源包之间的引用关系
- if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
- {
- if (buildParameters.BuildMode == EBuildMode.IncrementalBuild)
- {
- var buildResultContext = context.GetContextObject<TaskBuilding_SBP.BuildResultContext>();
- UpdateScriptPipelineReference(manifest, buildResultContext);
- }
- }
- // 更新资源包之间的引用关系
- if (buildParameters.BuildPipeline == EBuildPipeline.BuiltinBuildPipeline)
- {
- if (buildParameters.BuildMode != EBuildMode.SimulateBuild)
- {
- var buildResultContext = context.GetContextObject<TaskBuilding.BuildResultContext>();
- UpdateBuiltinPipelineReference(manifest, buildResultContext);
- }
- }
- // 创建补丁清单文本文件
- {
- string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
- string filePath = $"{packageOutputDirectory}/{fileName}";
- ManifestTools.SerializeToJson(filePath, manifest);
- BuildLogger.Log($"创建补丁清单文件:{filePath}");
- }
- // 创建补丁清单二进制文件
- string packageHash;
- {
- string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
- string filePath = $"{packageOutputDirectory}/{fileName}";
- ManifestTools.SerializeToBinary(filePath, manifest);
- packageHash = HashUtility.FileMD5(filePath);
- BuildLogger.Log($"创建补丁清单文件:{filePath}");
- ManifestContext manifestContext = new ManifestContext();
- byte[] bytesData = FileUtility.ReadAllBytes(filePath);
- manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData);
- context.SetContextObject(manifestContext);
- }
- // 创建补丁清单哈希文件
- {
- string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
- string filePath = $"{packageOutputDirectory}/{fileName}";
- FileUtility.WriteAllText(filePath, packageHash);
- BuildLogger.Log($"创建补丁清单哈希文件:{filePath}");
- }
- // 创建补丁清单版本文件
- {
- string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
- string filePath = $"{packageOutputDirectory}/{fileName}";
- FileUtility.WriteAllText(filePath, buildParameters.PackageVersion);
- BuildLogger.Log($"创建补丁清单版本文件:{filePath}");
- }
- }
- /// <summary>
- /// 获取资源包列表
- /// </summary>
- private List<PackageBundle> GetAllPackageBundle(BuildContext context)
- {
- var buildMapContext = context.GetContextObject<BuildMapContext>();
- List<PackageBundle> result = new List<PackageBundle>(1000);
- foreach (var bundleInfo in buildMapContext.Collection)
- {
- var packageBundle = bundleInfo.CreatePackageBundle();
- result.Add(packageBundle);
- }
- return result;
- }
- /// <summary>
- /// 获取资源列表
- /// </summary>
- private List<PackageAsset> GetAllPackageAsset(BuildContext context, PackageManifest manifest)
- {
- var buildMapContext = context.GetContextObject<BuildMapContext>();
- List<PackageAsset> result = new List<PackageAsset>(1000);
- foreach (var bundleInfo in buildMapContext.Collection)
- {
- var assetInfos = bundleInfo.GetAllManifestAssetInfos();
- foreach (var assetInfo in assetInfos)
- {
- PackageAsset packageAsset = new PackageAsset();
- packageAsset.Address = buildMapContext.Command.EnableAddressable ? assetInfo.Address : string.Empty;
- packageAsset.AssetPath = assetInfo.AssetPath;
- packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetGUID : string.Empty;
- packageAsset.AssetTags = assetInfo.AssetTags.ToArray();
- packageAsset.BundleID = GetCachedBundleID(assetInfo.BundleName);
- packageAsset.DependIDs = GetAssetBundleDependIDs(packageAsset.BundleID, assetInfo, manifest);
- result.Add(packageAsset);
- }
- }
- return result;
- }
- private int[] GetAssetBundleDependIDs(int mainBundleID, BuildAssetInfo assetInfo, PackageManifest manifest)
- {
- HashSet<int> result = new HashSet<int>();
- foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
- {
- if (dependAssetInfo.HasBundleName())
- {
- int bundleID = GetCachedBundleID(dependAssetInfo.BundleName);
- if (mainBundleID != bundleID)
- {
- if (result.Contains(bundleID) == false)
- result.Add(bundleID);
- }
- }
- }
- return result.ToArray();
- }
- /// <summary>
- /// 更新Unity内置资源包的引用关系
- /// </summary>
- private void UpdateBuiltInBundleReference(PackageManifest manifest, TaskBuilding_SBP.BuildResultContext buildResultContext, string shadersBunldeName)
- {
- // 获取所有依赖着色器资源包的资源包列表
- List<string> shaderBundleReferenceList = new List<string>();
- foreach (var valuePair in buildResultContext.Results.BundleInfos)
- {
- if (valuePair.Value.Dependencies.Any(t => t == shadersBunldeName))
- shaderBundleReferenceList.Add(valuePair.Key);
- }
- // 注意:没有任何资源依赖着色器
- if (shaderBundleReferenceList.Count == 0)
- return;
- // 获取着色器资源包索引
- Predicate<PackageBundle> predicate = new Predicate<PackageBundle>(s => s.BundleName == shadersBunldeName);
- int shaderBundleId = manifest.BundleList.FindIndex(predicate);
- if (shaderBundleId == -1)
- throw new Exception("没有发现着色器资源包!");
- // 检测依赖交集并更新依赖ID
- HashSet<string> tagTemps = new HashSet<string>();
- foreach (var packageAsset in manifest.AssetList)
- {
- List<string> dependBundles = GetPackageAssetAllDependBundles(manifest, packageAsset);
- List<string> conflictAssetPathList = dependBundles.Intersect(shaderBundleReferenceList).ToList();
- if (conflictAssetPathList.Count > 0)
- {
- HashSet<int> newDependIDs = new HashSet<int>(packageAsset.DependIDs);
- if (newDependIDs.Contains(shaderBundleId) == false)
- newDependIDs.Add(shaderBundleId);
- packageAsset.DependIDs = newDependIDs.ToArray();
- foreach (var tag in packageAsset.AssetTags)
- {
- if (tagTemps.Contains(tag) == false)
- tagTemps.Add(tag);
- }
- }
- }
- // 更新资源包标签
- var packageBundle = manifest.BundleList[shaderBundleId];
- HashSet<string> newTags = new HashSet<string>(packageBundle.Tags);
- foreach (var tag in tagTemps)
- {
- if (newTags.Contains(tag) == false)
- newTags.Add(tag);
- }
- packageBundle.Tags = newTags.ToArray();
- }
- private List<string> GetPackageAssetAllDependBundles(PackageManifest manifest, PackageAsset packageAsset)
- {
- List<string> result = new List<string>();
- string mainBundle = manifest.BundleList[packageAsset.BundleID].BundleName;
- result.Add(mainBundle);
- foreach (var dependID in packageAsset.DependIDs)
- {
- string dependBundle = manifest.BundleList[dependID].BundleName;
- result.Add(dependBundle);
- }
- return result;
- }
- #region 资源包引用关系相关
- private readonly Dictionary<string, int> _cachedBundleID = new Dictionary<string, int>(10000);
- private readonly Dictionary<string, string[]> _cachedBundleDepends = new Dictionary<string, string[]>(10000);
-
- private void CacheBundleIDs(PackageManifest manifest)
- {
- UnityEngine.Debug.Assert(manifest.BundleList.Count != 0, "Manifest bundle list is empty !");
- for (int index = 0; index < manifest.BundleList.Count; index++)
- {
- string bundleName = manifest.BundleList[index].BundleName;
- _cachedBundleID.Add(bundleName, index);
- }
- }
- private void UpdateScriptPipelineReference(PackageManifest manifest, TaskBuilding_SBP.BuildResultContext buildResultContext)
- {
- int progressValue;
- int totalCount = manifest.BundleList.Count;
- // 缓存资源包依赖
- _cachedBundleDepends.Clear();
- progressValue = 0;
- foreach (var packageBundle in manifest.BundleList)
- {
- if (packageBundle.IsRawFile)
- {
- _cachedBundleDepends.Add(packageBundle.BundleName, new string[] { });
- continue;
- }
- if (buildResultContext.Results.BundleInfos.ContainsKey(packageBundle.BundleName) == false)
- throw new Exception($"Not found bundle in SBP build results : {packageBundle.BundleName}");
- var depends = buildResultContext.Results.BundleInfos[packageBundle.BundleName].Dependencies;
- _cachedBundleDepends.Add(packageBundle.BundleName, depends);
- int pro = ++progressValue;
- if (pro % 100 == 0)
- {
- EditorTools.DisplayProgressBar("缓存资源包依赖列表", pro, totalCount);
- }
- }
- EditorTools.ClearProgressBar();
- // 计算资源包引用列表
- foreach (var packageBundle in manifest.BundleList)
- {
- packageBundle.ReferenceIDs = GetBundleRefrenceIDs(manifest, packageBundle);
- int pro = ++progressValue;
- if (pro % 100 == 0)
- {
- EditorTools.DisplayProgressBar("计算资源包引用关系", pro, totalCount);
- }
- }
- EditorTools.ClearProgressBar();
- }
- private void UpdateBuiltinPipelineReference(PackageManifest manifest, TaskBuilding.BuildResultContext buildResultContext)
- {
- int progressValue;
- int totalCount = manifest.BundleList.Count;
- // 缓存资源包依赖
- _cachedBundleDepends.Clear();
- progressValue = 0;
- foreach (var packageBundle in manifest.BundleList)
- {
- if (packageBundle.IsRawFile)
- {
- _cachedBundleDepends.Add(packageBundle.BundleName, new string[] { });
- continue;
- }
- var depends = buildResultContext.UnityManifest.GetDirectDependencies(packageBundle.BundleName);
- _cachedBundleDepends.Add(packageBundle.BundleName, depends);
- int pro = ++progressValue;
- if (pro % 100 == 0)
- {
- EditorTools.DisplayProgressBar("缓存资源包依赖列表", pro, totalCount);
- }
- }
- EditorTools.ClearProgressBar();
- // 计算资源包引用列表
- progressValue = 0;
- foreach (var packageBundle in manifest.BundleList)
- {
- packageBundle.ReferenceIDs = GetBundleRefrenceIDs(manifest, packageBundle);
- int pro = ++progressValue;
- if (pro % 100 == 0)
- {
- EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
- }
- }
- EditorTools.ClearProgressBar();
- }
- private int[] GetBundleRefrenceIDs(PackageManifest manifest, PackageBundle targetBundle)
- {
- List<string> referenceList = new List<string>();
- foreach (var packageBundle in manifest.BundleList)
- {
- string bundleName = packageBundle.BundleName;
- if (bundleName == targetBundle.BundleName)
- continue;
- string[] dependencies = GetCachedBundleDepends(bundleName);
- if (dependencies.Contains(targetBundle.BundleName))
- {
- referenceList.Add(bundleName);
- }
- }
- HashSet<int> result = new HashSet<int>();
- foreach (var bundleName in referenceList)
- {
- int bundleID = GetCachedBundleID(bundleName);
- if (result.Contains(bundleID) == false)
- result.Add(bundleID);
- }
- return result.ToArray();
- }
- private int GetCachedBundleID(string bundleName)
- {
- if (_cachedBundleID.TryGetValue(bundleName, out int value) == false)
- {
- throw new Exception($"Not found cached bundle ID : {bundleName}");
- }
- return value;
- }
- private string[] GetCachedBundleDepends(string bundleName)
- {
- if (_cachedBundleDepends.TryGetValue(bundleName, out string[] value) == false)
- {
- throw new Exception($"Not found cached bundle depends : {bundleName}");
- }
- return value;
- }
- #endregion
- }
- }
|