AssetBundleGroupsTask.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using XGame.Framework.Asset;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using XGame.Framework.Json;
  6. namespace XGame.Editor.Build.AssetBundles
  7. {
  8. internal class AssetBundleGroupsTask
  9. {
  10. public class AssetbundleGroupsManifest
  11. {
  12. //public UnityEditor.AssetBundleBuild[] bundleBuilds;
  13. public AssetbundleGroup[] bundleGroups;
  14. }
  15. public class AssetbundleGroup
  16. {
  17. public int groupId;
  18. public AssetbundleData[] bundles;
  19. }
  20. public class AssetbundleData
  21. {
  22. public uint bundleId;
  23. public int buildIndex;
  24. public uint[] dependencies;
  25. }
  26. public enum AbGroupMode
  27. {
  28. Normal = 0,
  29. Dependencies,
  30. }
  31. private string _outputPath;
  32. private AbGroupMode _groupMode;
  33. //public AssetBundleGroupsTask()
  34. //{
  35. // _outputPath = string.Empty;
  36. // _groupMode = AbGroupMode.Dependencies;
  37. //}
  38. public AssetBundleGroupsTask(string outputPath, AbGroupMode groupMode)
  39. {
  40. _outputPath = outputPath;
  41. _groupMode = groupMode;
  42. if (string.IsNullOrEmpty(outputPath))
  43. return;
  44. var dirPath = Path.GetDirectoryName(outputPath);
  45. if (!Directory.Exists(dirPath))
  46. {
  47. Directory.CreateDirectory(dirPath);
  48. BuildLog.Log($"AssetBundleGroupsTask CreateDirectory: {dirPath}");
  49. }
  50. }
  51. public bool Excute()
  52. {
  53. XBuildPipeline.GenerateBundleManifests();
  54. var manifest = AssetBundleUtils.LoadManifest();
  55. if (manifest == null || manifest.bundleInfos == null)
  56. return false;
  57. if (!BundleGroup(manifest.bundleInfos, out var bundleGroupMap))
  58. {
  59. return false;
  60. }
  61. return Export(manifest.bundleInfos, bundleGroupMap);
  62. }
  63. internal bool BundleGroup(AssetBundleInfo[] bundleInfos, out Dictionary<uint, int> bundleGroupMap)
  64. {
  65. if (_groupMode == AbGroupMode.Dependencies)
  66. {
  67. return BundleGroupByDependencies(bundleInfos, out bundleGroupMap);
  68. }
  69. return BundleGroupNormal(bundleInfos, out bundleGroupMap);
  70. }
  71. private bool BundleGroupNormal(AssetBundleInfo[] bundleInfos, out Dictionary<uint, int> bundleGroupMap)
  72. {
  73. bundleGroupMap = new Dictionary<uint, int>();
  74. var groupIndex = 0;
  75. var bundleIds = new HashSet<uint>();
  76. var groups = new HashSet<int>();
  77. foreach (var bundleInfo in bundleInfos)
  78. {
  79. //先找出该bundle和依赖的所有groupId
  80. var min = -1;
  81. if (bundleGroupMap.TryGetValue(bundleInfo.bundleId, out var groupId))
  82. {
  83. min = groupId;
  84. groups.Add(groupId);
  85. }
  86. if (bundleInfo.dependencies != null)
  87. {
  88. foreach (var dependence in bundleInfo.dependencies)
  89. {
  90. if (bundleGroupMap.TryGetValue(dependence, out groupId))
  91. {
  92. groups.Add(groupId);
  93. if (min == -1 || groupId < min)
  94. min = groupId;
  95. }
  96. }
  97. }
  98. if (groups.Count > 0)
  99. {
  100. groups.Remove(min);
  101. if (groups.Count > 0)
  102. {
  103. //关联的bundle也必须同步修改groupId
  104. foreach (var key in bundleIds)
  105. {
  106. var val = bundleGroupMap[key];
  107. if (groups.Contains(val))
  108. {
  109. bundleGroupMap[key] = min;
  110. }
  111. }
  112. }
  113. //取groupId最小值
  114. groupId = min;
  115. }
  116. else
  117. {
  118. //新增一个Group
  119. groupId = groupIndex++;
  120. }
  121. //设置GroupId
  122. if (!bundleGroupMap.ContainsKey(bundleInfo.bundleId))
  123. {
  124. bundleGroupMap[bundleInfo.bundleId] = groupId;
  125. bundleIds.Add(bundleInfo.bundleId);
  126. }
  127. if (bundleInfo.dependencies != null)
  128. {
  129. foreach (var dependence in bundleInfo.dependencies)
  130. {
  131. if (!bundleGroupMap.ContainsKey(dependence))
  132. {
  133. bundleGroupMap[dependence] = groupId;
  134. bundleIds.Add(dependence);
  135. }
  136. }
  137. }
  138. //清除缓存
  139. groups.Clear();
  140. }
  141. return true;
  142. }
  143. private bool BundleGroupByDependencies(AssetBundleInfo[] bundleInfos, out Dictionary<uint, int> bundleGroupMap)
  144. {
  145. bundleGroupMap = new Dictionary<uint, int>();
  146. var bundlesMap = new Dictionary<uint, AssetBundleInfo>();
  147. var bundleIds = new List<uint>();
  148. foreach (var bundleInfo in bundleInfos)
  149. {
  150. bundlesMap.Add(bundleInfo.bundleId, bundleInfo);
  151. if (bundleInfo.DependenciesCount == 0)
  152. {
  153. bundleGroupMap.Add(bundleInfo.bundleId, 0);
  154. }
  155. else
  156. {
  157. bundleIds.Add(bundleInfo.bundleId);
  158. }
  159. }
  160. var groupId = 1;
  161. var tempIds = new List<uint>();
  162. while (bundleIds.Count > 0)
  163. {
  164. foreach (var bundleId in bundleIds)
  165. {
  166. var bundleInfo = bundlesMap[bundleId];
  167. var isTrue = true;
  168. foreach (var dep in bundleInfo.dependencies)
  169. {
  170. if (!bundleGroupMap.ContainsKey(dep))
  171. {
  172. isTrue = false;
  173. break;
  174. }
  175. }
  176. if (isTrue)
  177. {
  178. tempIds.Add(bundleId);
  179. }
  180. }
  181. if (tempIds.Count > 0)
  182. {
  183. foreach (var bundleId in tempIds)
  184. {
  185. bundleIds.Remove(bundleId);
  186. bundleGroupMap.Add(bundleId, groupId);
  187. }
  188. groupId += 1;
  189. tempIds.Clear();
  190. }
  191. else
  192. {
  193. Log.Error($"Assetbundle分组失败。已分数量:{bundleGroupMap.Count} 剩余:{bundleIds.Count} Group:{groupId}");
  194. return false;
  195. }
  196. }
  197. return true;
  198. }
  199. private bool Export(AssetBundleInfo[] bundleInfos, Dictionary<uint, int> bundleGroupMap)
  200. {
  201. var outputPath = _outputPath;
  202. var abCount = bundleInfos.Length;
  203. var manifest = new AssetbundleGroupsManifest()
  204. {
  205. //bundleBuilds = new UnityEditor.AssetBundleBuild[abCount],
  206. };
  207. var bundleDataMap = new Dictionary<uint, AssetbundleData>();
  208. var abIndex = 0;
  209. foreach (var bundleInfo in bundleInfos)
  210. {
  211. var bundleId = bundleInfo.bundleId;
  212. bundleDataMap[bundleId] = new AssetbundleData()
  213. {
  214. bundleId = bundleId,
  215. buildIndex = abIndex,
  216. dependencies = bundleInfo.dependencies,
  217. };
  218. //manifest.bundleBuilds[abIndex] = bundleBuildMap[bundleId].ToUniBuild();
  219. abIndex++;
  220. }
  221. var bundleGroups = bundleGroupMap.GroupBy(item => item.Value);
  222. var groupCount = bundleGroups.Count();
  223. var abGroups = new List<AssetbundleGroup>();
  224. foreach (var bundleGroup in bundleGroups)
  225. {
  226. var count = bundleGroup.Count();
  227. var abGroup = new AssetbundleGroup()
  228. {
  229. groupId = bundleGroup.Key,
  230. bundles = new AssetbundleData[count],
  231. };
  232. var bundleIdx = 0;
  233. foreach (var item in bundleGroup)
  234. {
  235. abGroup.bundles[bundleIdx++] = bundleDataMap[item.Key];
  236. }
  237. abGroups.Add(abGroup);
  238. }
  239. abGroups.Sort((a, b) => a.groupId - b.groupId);
  240. manifest.bundleGroups = abGroups.ToArray();
  241. var text = XJson.ToJson(manifest);
  242. File.WriteAllText(outputPath, text, System.Text.Encoding.UTF8);
  243. BuildLog.Log($"GenAssetbundleGroups finish. GroupCount:{groupCount} Path:{outputPath}");
  244. return true;
  245. }
  246. }
  247. }