TaskGetBuildMap.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEditor;
  7. namespace YooAsset.Editor
  8. {
  9. public class TaskGetBuildMap
  10. {
  11. /// <summary>
  12. /// 生成资源构建上下文
  13. /// </summary>
  14. public BuildMapContext CreateBuildMap(bool simulateBuild, BuildParameters buildParameters)
  15. {
  16. BuildMapContext context = new BuildMapContext();
  17. var packageName = buildParameters.PackageName;
  18. Dictionary<string, BuildAssetInfo> allBuildAssetInfos = new Dictionary<string, BuildAssetInfo>(1000);
  19. // 1. 获取所有收集器收集的资源
  20. bool useAssetDependencyDB = buildParameters.UseAssetDependencyDB;
  21. var collectResult = AssetBundleCollectorSettingData.Setting.BeginCollect(packageName, simulateBuild, useAssetDependencyDB);
  22. List<CollectAssetInfo> allCollectAssets = collectResult.CollectAssets;
  23. // 2. 剔除未被引用的依赖项资源
  24. RemoveZeroReferenceAssets(context, allCollectAssets);
  25. // 3. 录入所有收集器主动收集的资源
  26. foreach (var collectAssetInfo in allCollectAssets)
  27. {
  28. if (allBuildAssetInfos.ContainsKey(collectAssetInfo.AssetInfo.AssetPath))
  29. {
  30. throw new Exception($"Should never get here !");
  31. }
  32. if (collectAssetInfo.CollectorType != ECollectorType.MainAssetCollector)
  33. {
  34. if (collectAssetInfo.AssetTags.Count > 0)
  35. {
  36. collectAssetInfo.AssetTags.Clear();
  37. string warning = BuildLogger.GetErrorMessage(ErrorCode.RemoveInvalidTags, $"Remove asset tags that don't work, see the asset collector type : {collectAssetInfo.AssetInfo.AssetPath}");
  38. BuildLogger.Warning(warning);
  39. }
  40. }
  41. var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.CollectorType, collectAssetInfo.BundleName, collectAssetInfo.Address, collectAssetInfo.AssetInfo);
  42. buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
  43. allBuildAssetInfos.Add(collectAssetInfo.AssetInfo.AssetPath, buildAssetInfo);
  44. }
  45. // 4. 录入所有收集资源依赖的其它资源
  46. foreach (var collectAssetInfo in allCollectAssets)
  47. {
  48. string bundleName = collectAssetInfo.BundleName;
  49. foreach (var dependAsset in collectAssetInfo.DependAssets)
  50. {
  51. if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out var value))
  52. {
  53. value.AddReferenceBundleName(bundleName);
  54. }
  55. else
  56. {
  57. var buildAssetInfo = new BuildAssetInfo(dependAsset);
  58. buildAssetInfo.AddReferenceBundleName(bundleName);
  59. allBuildAssetInfos.Add(dependAsset.AssetPath, buildAssetInfo);
  60. }
  61. }
  62. }
  63. // 5. 填充所有收集资源的依赖列表
  64. foreach (var collectAssetInfo in allCollectAssets)
  65. {
  66. var dependAssetInfos = new List<BuildAssetInfo>(collectAssetInfo.DependAssets.Count);
  67. foreach (var dependAsset in collectAssetInfo.DependAssets)
  68. {
  69. if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out BuildAssetInfo value))
  70. dependAssetInfos.Add(value);
  71. else
  72. throw new Exception("Should never get here !");
  73. }
  74. allBuildAssetInfos[collectAssetInfo.AssetInfo.AssetPath].SetDependAssetInfos(dependAssetInfos);
  75. }
  76. // 6. 自动收集所有依赖的着色器
  77. if (collectResult.Command.AutoCollectShaders)
  78. {
  79. // 获取着色器打包规则结果
  80. PackRuleResult shaderPackRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
  81. string shaderBundleName = shaderPackRuleResult.GetBundleName(collectResult.Command.PackageName, collectResult.Command.UniqueBundleName);
  82. foreach (var buildAssetInfo in allBuildAssetInfos.Values)
  83. {
  84. if (buildAssetInfo.CollectorType == ECollectorType.None)
  85. {
  86. if (buildAssetInfo.AssetInfo.IsShaderAsset())
  87. {
  88. buildAssetInfo.SetBundleName(shaderBundleName);
  89. }
  90. }
  91. }
  92. }
  93. // 7. 计算共享资源的包名
  94. if (buildParameters.EnableSharePackRule)
  95. {
  96. PreProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
  97. foreach (var buildAssetInfo in allBuildAssetInfos.Values)
  98. {
  99. if (buildAssetInfo.HasBundleName() == false)
  100. {
  101. ProcessingPackShareBundle(buildParameters, collectResult.Command, buildAssetInfo);
  102. }
  103. }
  104. PostProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
  105. }
  106. // 8. 记录关键信息
  107. context.AssetFileCount = allBuildAssetInfos.Count;
  108. context.Command = collectResult.Command;
  109. // 9. 移除不参与构建的资源
  110. List<BuildAssetInfo> removeBuildList = new List<BuildAssetInfo>();
  111. foreach (var buildAssetInfo in allBuildAssetInfos.Values)
  112. {
  113. if (buildAssetInfo.HasBundleName() == false)
  114. removeBuildList.Add(buildAssetInfo);
  115. }
  116. foreach (var removeValue in removeBuildList)
  117. {
  118. allBuildAssetInfos.Remove(removeValue.AssetInfo.AssetPath);
  119. }
  120. // 10. 构建资源列表
  121. var allPackAssets = allBuildAssetInfos.Values.ToList();
  122. if (allPackAssets.Count == 0)
  123. {
  124. string message = BuildLogger.GetErrorMessage(ErrorCode.PackAssetListIsEmpty, "The pack asset info is empty !");
  125. throw new Exception(message);
  126. }
  127. foreach (var assetInfo in allPackAssets)
  128. {
  129. context.PackAsset(assetInfo);
  130. }
  131. return context;
  132. }
  133. private void RemoveZeroReferenceAssets(BuildMapContext context, List<CollectAssetInfo> allCollectAssets)
  134. {
  135. // 1. 检测依赖资源收集器是否存在
  136. if (allCollectAssets.Exists(x => x.CollectorType == ECollectorType.DependAssetCollector) == false)
  137. return;
  138. // 2. 获取所有主资源的依赖资源集合
  139. HashSet<string> allDependAsset = new HashSet<string>();
  140. foreach (var collectAsset in allCollectAssets)
  141. {
  142. var collectorType = collectAsset.CollectorType;
  143. if (collectorType == ECollectorType.MainAssetCollector || collectorType == ECollectorType.StaticAssetCollector)
  144. {
  145. foreach (var dependAsset in collectAsset.DependAssets)
  146. {
  147. if (allDependAsset.Contains(dependAsset.AssetPath) == false)
  148. allDependAsset.Add(dependAsset.AssetPath);
  149. }
  150. }
  151. }
  152. // 3. 找出所有零引用的依赖资源集合
  153. List<CollectAssetInfo> removeList = new List<CollectAssetInfo>();
  154. foreach (var collectAssetInfo in allCollectAssets)
  155. {
  156. var collectorType = collectAssetInfo.CollectorType;
  157. if (collectorType == ECollectorType.DependAssetCollector)
  158. {
  159. if (allDependAsset.Contains(collectAssetInfo.AssetInfo.AssetPath) == false)
  160. removeList.Add(collectAssetInfo);
  161. }
  162. }
  163. // 4. 移除所有零引用的依赖资源
  164. foreach (var removeValue in removeList)
  165. {
  166. string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundUndependedAsset, $"Found undepended asset and remove it : {removeValue.AssetInfo.AssetPath}");
  167. BuildLogger.Warning(warning);
  168. var independAsset = new ReportIndependAsset();
  169. independAsset.AssetPath = removeValue.AssetInfo.AssetPath;
  170. independAsset.AssetGUID = removeValue.AssetInfo.AssetGUID;
  171. independAsset.AssetType = removeValue.AssetInfo.AssetType.ToString();
  172. independAsset.FileSize = FileUtility.GetFileSize(removeValue.AssetInfo.AssetPath);
  173. context.IndependAssets.Add(independAsset);
  174. allCollectAssets.Remove(removeValue);
  175. }
  176. }
  177. #region 共享资源打包规则
  178. /// <summary>
  179. /// 共享资源打包前置处理
  180. /// </summary>
  181. protected virtual void PreProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
  182. {
  183. }
  184. /// <summary>
  185. /// 共享资源打包机制
  186. /// </summary>
  187. protected virtual void ProcessingPackShareBundle(BuildParameters buildParameters, CollectCommand command, BuildAssetInfo buildAssetInfo)
  188. {
  189. PackRuleResult packRuleResult = GetShareBundleName(buildAssetInfo);
  190. if (packRuleResult.IsValid() == false)
  191. return;
  192. // 处理单个引用的共享资源
  193. if (buildAssetInfo.GetReferenceBundleCount() <= 1)
  194. {
  195. if (buildParameters.SingleReferencedPackAlone == false)
  196. return;
  197. }
  198. // 设置共享资源包名
  199. string shareBundleName = packRuleResult.GetShareBundleName(command.PackageName, command.UniqueBundleName);
  200. buildAssetInfo.SetBundleName(shareBundleName);
  201. }
  202. private PackRuleResult GetShareBundleName(BuildAssetInfo buildAssetInfo)
  203. {
  204. string bundleName = Path.GetDirectoryName(buildAssetInfo.AssetInfo.AssetPath);
  205. PackRuleResult result = new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension);
  206. return result;
  207. }
  208. /// <summary>
  209. /// 共享资源打包后置处理
  210. /// </summary>
  211. protected virtual void PostProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
  212. {
  213. }
  214. #endregion
  215. }
  216. }