BundleDepsController.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace XGame.Editor.Build.AssetBundles
  6. {
  7. /// <summary>
  8. /// 收集bundle依赖
  9. /// </summary>
  10. internal class BundleDepsController
  11. {
  12. private BundleContext _context;
  13. public BundleDepsController(BundleContext context)
  14. {
  15. _context = context;
  16. }
  17. /// <summary>
  18. /// key: assetPath
  19. /// value: bundleId
  20. /// </summary>
  21. /// <returns></returns>
  22. private Dictionary<string, uint> GetAssetPathMap()
  23. {
  24. var assetPathMap = new Dictionary<string, uint>();
  25. foreach (var keyValue in _context.bundleDataMap)
  26. {
  27. var build = keyValue.Value;
  28. foreach (var assetPath in build.assetNames)
  29. {
  30. if (assetPathMap.ContainsKey(assetPath))
  31. {
  32. BuildLog.Error($"assetPath repeat. Id:{build.bundleId} Name:{build.originBundleName} Asset:{assetPath}");
  33. }
  34. else
  35. {
  36. assetPathMap.Add(assetPath, build.bundleId);
  37. }
  38. }
  39. }
  40. return assetPathMap;
  41. }
  42. /// <summary>
  43. /// 收集所有bundle的依赖bundleId
  44. /// </summary>
  45. /// <returns></returns>
  46. public bool CollectBundleDependencies()
  47. {
  48. var assetPathToBundleIdMap = GetAssetPathMap();
  49. var dependenciesMap = _context.dependenciesMap;
  50. dependenciesMap.Clear();
  51. var depAssetsMap = new Dictionary<long, HashSet<string>>();
  52. int index = 0;
  53. var tempAssetPaths = new HashSet<string>();
  54. foreach (var item in _context.bundleDataMap)
  55. {
  56. EditorUtility.DisplayProgressBar("Collect Asset Dependencies", item.Value.assetBundleName, (++index) / (float)_context.bundleDataMap.Count);
  57. tempAssetPaths.UnionWith(item.Value.assetNames);
  58. var assetPaths = new HashSet<string>();
  59. if (item.Value.isTextureBundle == false)
  60. { //全是贴图的bundle不用查找
  61. var dependencies = _context.GetDependencies(item.Value.bundleId, item.Value.assetNames);
  62. foreach (var depPath in dependencies)
  63. {
  64. if (assetPathToBundleIdMap.ContainsKey(depPath) && !tempAssetPaths.Contains(depPath))
  65. {
  66. assetPaths.Add(depPath);
  67. }
  68. }
  69. }
  70. depAssetsMap.Add(item.Key, assetPaths);
  71. tempAssetPaths.Clear();
  72. }
  73. EditorUtility.ClearProgressBar();
  74. Debug.Log($"AssetBundle GetDependencies Time:{_context.bundleDependenciesSw.ElapsedMilliseconds}");
  75. var bundleIds = new HashSet<long>();
  76. foreach (var item in depAssetsMap)
  77. {
  78. if (item.Value.Count == 0)
  79. {
  80. dependenciesMap.Add(item.Key, new uint[0]);
  81. //Debug.Log($"Assetbundle依赖为零. Name:{item.Key}");
  82. }
  83. else
  84. {
  85. bundleIds.Add(item.Key);
  86. }
  87. }
  88. var tempIds = new HashSet<long>();
  89. var depBundleIds = new List<uint>();
  90. while (bundleIds.Count > 0)
  91. {
  92. EditorUtility.DisplayProgressBar("Collect Bundle Dependencies", $"剩余: {bundleIds.Count}", dependenciesMap.Count / (float)_context.bundleDataMap.Count);
  93. foreach (var bundleId in bundleIds)
  94. {
  95. var dependencies = depAssetsMap[bundleId];
  96. var isTrue = true;
  97. foreach (var dependency in dependencies)
  98. {
  99. var depBundleId = assetPathToBundleIdMap[dependency];
  100. if (!dependenciesMap.ContainsKey(depBundleId))
  101. {
  102. isTrue = false;
  103. break;
  104. }
  105. }
  106. if (isTrue)
  107. {
  108. tempIds.Add(bundleId);
  109. }
  110. }
  111. if (tempIds.Count > 0)
  112. {
  113. foreach (var bundleId in tempIds)
  114. {
  115. bundleIds.Remove(bundleId);
  116. var dependencies = depAssetsMap[bundleId];
  117. foreach (var dependency in dependencies)
  118. {
  119. var depId = (uint)assetPathToBundleIdMap[dependency];
  120. depBundleIds.Add(depId);
  121. depBundleIds.AddRange(dependenciesMap[depId]);
  122. //if (bundleId == 2940165715 || bundleId == 1899048051 || bundleId == 2238712722)
  123. //{
  124. // var sb = new System.Text.StringBuilder();
  125. // sb.Append(bundleId);
  126. // sb.Append(" depBundle:");
  127. // sb.Append(depId);
  128. // sb.Append(" dependencies:");
  129. // foreach (var item in depBundleIdsMap[depId])
  130. // {
  131. // sb.Append(item);
  132. // sb.Append("; ");
  133. // }
  134. // Debug.Log(sb.ToString());
  135. //}
  136. }
  137. depBundleIds = depBundleIds.Distinct().ToList();
  138. depBundleIds.Remove((uint)bundleId);
  139. dependenciesMap.Add(bundleId, depBundleIds.ToArray());
  140. depBundleIds.Clear();
  141. }
  142. tempIds.Clear();
  143. }
  144. else
  145. {
  146. EditorUtility.ClearProgressBar();
  147. //理论上这个肯定不会触发
  148. Log.Error($"CollectBundleDependencies failed. 如果是Assetbundle出现互相依赖,请调整相关资源使相互依赖的Asset在同一个Assetbundle内. Success: {dependenciesMap.Count} Failure: {bundleIds.Count}");
  149. foreach (var bundleId in bundleIds)
  150. {
  151. var build = _context.bundleDataMap[bundleId];
  152. var dependencies = depAssetsMap[bundleId];
  153. foreach (var dep in dependencies)
  154. {
  155. if (assetPathToBundleIdMap.TryGetValue(dep, out var depBundleId) && dependenciesMap.ContainsKey(depBundleId) == false)
  156. {
  157. Log.Error($"bundleId:{bundleId} Name:{build.originBundleName} dependence:{dep} depBundleId:{depBundleId}");
  158. }
  159. }
  160. }
  161. return false;
  162. }
  163. }
  164. EditorUtility.ClearProgressBar();
  165. return true;
  166. }
  167. }
  168. }