AssetBundleLoadManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Text.RegularExpressions;
  6. using Core.AssetLoadTool.Asset;
  7. using Fort23.Core;
  8. using Fort23.UTool;
  9. #if !COMBAT_SERVER
  10. using UnityEngine;
  11. using UnityEngine.Networking;
  12. using Object = UnityEngine.Object;
  13. using Utility;
  14. public class AssetBundleLoadManager : Singleton<AssetBundleLoadManager>
  15. {
  16. public BundleLoadType BundleLoadType;
  17. public string h5Url;
  18. public bool UnloadType = true;
  19. public bool stopUpdate;
  20. private string m_rootStreamingURL;
  21. public string RootStreamingURL
  22. {
  23. get { return m_rootStreamingURL; }
  24. }
  25. private string m_rootStreamingBundleURL;
  26. public string RootStreamingBundleURL
  27. {
  28. get { return m_rootStreamingBundleURL; }
  29. }
  30. private string m_rootPersistentBundleURL;
  31. public string RootPersistentBundleURL
  32. {
  33. get { return m_rootPersistentBundleURL; }
  34. }
  35. public string manifestName
  36. {
  37. get { return m_manifestName; }
  38. }
  39. private string m_manifestName;
  40. private string m_globalConfigName;
  41. private string m_buildNoName;
  42. private string m_assetConfigName;
  43. public float gcTime;
  44. public Map<string, AssetInfo> assetToBundleDict = new Map<string, AssetInfo>();
  45. private AssetBundleManifest assetBundleManifest = null;
  46. private Dictionary<string, string> assetBundleHash = new Dictionary<string, string>();
  47. private int index = 0;
  48. private System.Action loadEndCallBack;
  49. public Map<AssetInfo, AssetLoadTaskBasic> m_currLoadAsset = new Map<AssetInfo, AssetLoadTaskBasic>();
  50. public Map<string, BundleLoadBasic> m_currLoadBundle = new Map<string, BundleLoadBasic>();
  51. public bool isSceneLoad;
  52. private List<BundleLoadBasic> bundleUnloadBuffer = new List<BundleLoadBasic>();
  53. public List<BundleLoadBasic> dependenciesBuffer = new List<BundleLoadBasic>();
  54. public bool isUnload;
  55. public System.Action<string> onLoadAsset;
  56. public AssetBundleLoadManager()
  57. {
  58. SetFileRoot();
  59. }
  60. public async CTask InitAssetsManager(System.Action loadEndCallBack)
  61. {
  62. // Ctask
  63. CTask cTask = CTask.Create(false);
  64. LogTool.Log("kaishijiazai asset");
  65. this.loadEndCallBack = delegate
  66. {
  67. cTask.SetResult();
  68. loadEndCallBack?.Invoke();
  69. };
  70. index = 0;
  71. //Load assetconfig file.
  72. LoadAssetConfig(null);
  73. //Load manifest file.
  74. LoadManifest();
  75. await cTask;
  76. }
  77. public void UnloadBundleBuffer()
  78. {
  79. LogTool.Log("卸载数据");
  80. for (int i = 0; i < bundleUnloadBuffer.Count; i++)
  81. {
  82. bundleUnloadBuffer[i].UnloadBundle();
  83. }
  84. bundleUnloadBuffer.Clear();
  85. }
  86. public void CallBackLoadEnd()
  87. {
  88. index++;
  89. if (index >= 2)
  90. {
  91. loadEndCallBack();
  92. }
  93. }
  94. private void SetFileRoot()
  95. {
  96. m_rootStreamingURL = Application.streamingAssetsPath;
  97. m_rootStreamingBundleURL = m_rootStreamingURL + "/Bundle/";
  98. m_rootPersistentBundleURL = Application.persistentDataPath + "/Bundle/";
  99. #if UNITY_EDITOR
  100. m_assetConfigName = Application.streamingAssetsPath +
  101. "/assetConfig.txt";
  102. #elif UNITY_IPHONE
  103. m_rootStreamingURL = "file://" + m_rootStreamingURL;
  104. m_rootStreamingBundleURL = "file://" + m_rootStreamingBundleURL;
  105. m_assetConfigName = m_rootPersistentBundleURL +
  106. "assetConfig.txt";
  107. #else
  108. m_assetConfigName = m_rootPersistentBundleURL +
  109. "assetConfig.txt";
  110. #endif
  111. m_manifestName = "UnityBundle";
  112. //Temp path. When version update is ready, path will be persistentPath and streamingPath.
  113. // m_rootpersistentBundleURL = Application.persistentDataPath + "/BundlAsset/";
  114. }
  115. private Dictionary<string, string> GetABNamesWithHash(AssetBundleManifest abm)
  116. {
  117. var hashNames = abm.GetAllAssetBundles();
  118. Dictionary<string, string> ABNamesDict =
  119. new Dictionary<string, string>();
  120. foreach (var hashName in hashNames)
  121. {
  122. //需要注意AB后缀名,默认 .unity3d
  123. var abName = Regex.Match(hashName,
  124. "_[0-9a-f]{32}").Success
  125. ? hashName.Substring(0, hashName.Length - 33)
  126. : hashName;
  127. ABNamesDict.Add(abName, hashName);
  128. }
  129. return ABNamesDict;
  130. }
  131. public void LoadAssetConfig(System.Action callBack)
  132. {
  133. DoLoadingAssetConfig(m_assetConfigName, callBack);
  134. }
  135. private void DoLoadingAssetConfig(string url, System.Action callBack)
  136. {
  137. assetToBundleDict.Clear();
  138. if (BundleLoadType != BundleLoadType.H5 && File.Exists(url))
  139. {
  140. Debug.Log("URL:" + url);
  141. string data = File.ReadAllText(url);
  142. LoadPackedInfo(data, callBack);
  143. }
  144. else
  145. {
  146. // url = m_rootStreamingURL +
  147. if (BundleLoadType != BundleLoadType.H5)
  148. {
  149. url = m_rootStreamingBundleURL + "assetConfig.txt";
  150. }
  151. else
  152. {
  153. url = h5Url + "assetConfig.txt";
  154. }
  155. Debug.Log("URL22:" + url);
  156. Uri uri = new Uri(url);
  157. UnityWebRequest unityWebRequest = UnityWebRequest.Get(uri);
  158. unityWebRequest.SetRequestHeader("Content-Type", "application/json");
  159. unityWebRequest.SetRequestHeader("Accept", "application/json");
  160. unityWebRequest.certificateHandler = new CustomCertificateHandler();
  161. UnityWebRequestAsyncOperation webRequestAsyncOperation = unityWebRequest.SendWebRequest();
  162. webRequestAsyncOperation.completed += delegate(AsyncOperation operation)
  163. {
  164. if (!string.IsNullOrEmpty(webRequestAsyncOperation.webRequest.downloadHandler.error))
  165. {
  166. LogTool.Error(Application.streamingAssetsPath + "m_assetConfigName buchunzai" + m_assetConfigName);
  167. LogTool.Error(webRequestAsyncOperation.webRequest.downloadHandler.error);
  168. }
  169. else
  170. {
  171. LoadPackedInfo(webRequestAsyncOperation.webRequest.downloadHandler.text, callBack);
  172. }
  173. };
  174. }
  175. return;
  176. }
  177. private void LoadPackedInfo(string json, System.Action callBack)
  178. {
  179. // Debug.Log(json);
  180. AllPackedAssetsInfo allPackedInfo = JsonManager.FromJson<AllPackedAssetsInfo>(json);
  181. Debug.Log(allPackedInfo != null);
  182. Debug.Log(allPackedInfo.assetsList.Count);
  183. for (int i = 0; i < allPackedInfo.assetsList.Count; i++)
  184. {
  185. AssetInfo assetInfo = allPackedInfo.assetsList[i];
  186. if (assetInfo != null)
  187. {
  188. assetToBundleDict.Add(assetInfo.name, assetInfo);
  189. }
  190. }
  191. if (callBack != null)
  192. callBack();
  193. CallBackLoadEnd();
  194. }
  195. private void LoadManifest()
  196. {
  197. DoLoadingManifest();
  198. }
  199. private void DoLoadingManifest()
  200. {
  201. string url = RootPersistentBundleURL + m_manifestName;
  202. if (BundleLoadType != BundleLoadType.H5 && !File.Exists(url))
  203. {
  204. url = Application.streamingAssetsPath + "/Bundle/" + m_manifestName;
  205. }
  206. if (BundleLoadType == BundleLoadType.LocalAsset)
  207. {
  208. CallBackLoadEnd();
  209. return;
  210. }
  211. if (BundleLoadType == BundleLoadType.H5)
  212. {
  213. url = h5Url + m_manifestName;
  214. }
  215. Debug.Log(url);
  216. UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url);
  217. webRequest.certificateHandler = new CustomCertificateHandler();
  218. UnityWebRequestAsyncOperation webRequestAsyncOperation = webRequest.SendWebRequest();
  219. // AssetBundleCreateRequest bundlReq = AssetBundle.LoadFromFileAsync(url);
  220. webRequestAsyncOperation.completed += delegate(AsyncOperation operation)
  221. {
  222. DownloadHandlerAssetBundle downloadHandler = webRequest.downloadHandler as DownloadHandlerAssetBundle;
  223. assetBundleManifest = downloadHandler.assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  224. if (assetBundleManifest != null)
  225. {
  226. LogTool.Log("AssetBundleManifest jizaiwancheng");
  227. }
  228. assetBundleHash = GetABNamesWithHash(assetBundleManifest);
  229. downloadHandler.assetBundle.Unload(false);
  230. CallBackLoadEnd();
  231. };
  232. }
  233. public string[] GetBundleDependencies(string bundleName)
  234. {
  235. if (assetBundleManifest == null)
  236. {
  237. return null;
  238. }
  239. return assetBundleManifest.GetDirectDependencies(bundleName);
  240. }
  241. public async CTask<AssetHandle> LoadAssetAsyncTask<T>(string assetName,
  242. System.Action<AssetHandle> callBack = null, Clock clock = null, bool isUseSynchronous = false) where T : Object
  243. {
  244. onLoadAsset?.Invoke(assetName);
  245. //临时使用到007的bundle加载,现在这个bundel卸载有遗漏,后面有时间了在改
  246. CTask task = CTask.Create(false);
  247. AssetHandle obj = null;
  248. LoadAssetAsync<T>(assetName, delegate(AssetHandle o, object o1)
  249. {
  250. if (o != null)
  251. {
  252. obj = o;
  253. }
  254. task.SetResult();
  255. }, clock, isUseSynchronous);
  256. await task;
  257. // TODO 暂时去掉,不知道会不会有影响
  258. // await TimerComponent.Instance.WaitFrameAsync();
  259. callBack?.Invoke(obj);
  260. return obj;
  261. }
  262. private void LoadAssetAsync<T>(string assetName, System.Action<AssetHandle, object> callBack, Clock clock = null,
  263. object userData = null, bool isUseSynchronous = false) where T : Object
  264. {
  265. if (!assetToBundleDict.TryGetValue(assetName, out AssetInfo assetInfo))
  266. {
  267. callBack?.Invoke(null, userData);
  268. Debug.LogWarning("没找到资源" + assetName);
  269. return;
  270. }
  271. LoadAssetCallBackData loadAssetCallBackData = new LoadAssetCallBackData();
  272. loadAssetCallBackData.loadEndCallBack = callBack;
  273. loadAssetCallBackData.userData = userData;
  274. loadAssetCallBackData.Clock = clock;
  275. loadAssetCallBackData.isUseSynchronous = isUseSynchronous;
  276. AssetLoadTaskBasic assetLoad = null;
  277. if (!m_currLoadAsset.TryGetValue(assetInfo, out assetLoad))
  278. {
  279. assetLoad = CreateAssetTaskBasic();
  280. assetLoad.InitAsset<T>(assetInfo, UnloadType, loadAssetCallBackData);
  281. m_currLoadAsset.Add(assetInfo, assetLoad);
  282. }
  283. else
  284. {
  285. assetLoad.AddCallBack<T>(loadAssetCallBackData);
  286. }
  287. }
  288. protected AssetLoadTaskBasic CreateAssetTaskBasic()
  289. {
  290. switch (BundleLoadType)
  291. {
  292. case BundleLoadType.LocalAsset:
  293. return new LocalAssetLoadTask();
  294. break;
  295. case BundleLoadType.LocalBundle:
  296. return new BundleAssetLoadTask();
  297. break;
  298. case BundleLoadType.H5:
  299. return new BundleAssetLoadTask();
  300. break;
  301. }
  302. LogTool.Error("加载模式不存在" + BundleLoadType);
  303. return null;
  304. }
  305. protected BundleLoadBasic CreateBundleTaskBasic()
  306. {
  307. switch (BundleLoadType)
  308. {
  309. case BundleLoadType.LocalAsset:
  310. break;
  311. case BundleLoadType.LocalBundle:
  312. return new LocalBundleLoadTask();
  313. break;
  314. case BundleLoadType.H5:
  315. return new H5BundleLoadTask();
  316. break;
  317. }
  318. LogTool.Error("加载模式不存在" + BundleLoadType);
  319. return null;
  320. }
  321. public BundleLoadBasic AddBundleTask(string bundleName, System.Action<BundleLoadBasic, object> callBack,
  322. LoadTaskBasic loadTaskBasic)
  323. {
  324. BundleLoadBasic bundleLoadTask = null;
  325. if (assetBundleHash.TryGetValue(bundleName, out string hash))
  326. {
  327. bundleName = hash;
  328. }
  329. if (m_currLoadBundle.ContainsKey(bundleName))
  330. {
  331. bundleLoadTask = m_currLoadBundle[bundleName];
  332. }
  333. if (bundleLoadTask == null)
  334. {
  335. bundleLoadTask = CreateBundleTaskBasic();
  336. //AssetInfo bundleInfo = assetToBundleDict[assetName];
  337. m_currLoadBundle.Add(bundleName, bundleLoadTask);
  338. bundleLoadTask.InitBundle(bundleName, UnloadType, callBack);
  339. bundleLoadTask.AddOwnTask(loadTaskBasic);
  340. }
  341. else
  342. {
  343. bundleLoadTask.AddOwnTask(loadTaskBasic);
  344. bundleLoadTask.AddCallBack(callBack);
  345. }
  346. return bundleLoadTask;
  347. }
  348. public string GetBudnleInfo()
  349. {
  350. return $"当前拥有资源数:{m_currLoadAsset.Count} bundle数:{m_currLoadBundle.Count}";
  351. }
  352. public void UpdateBundle()
  353. {
  354. if (stopUpdate)
  355. return;
  356. BundleLoadBasic[] depend = dependenciesBuffer.ToArray();
  357. for (int i = 0; i < depend.Length; i++)
  358. {
  359. if (depend[i].AwaitDependenceLoadEnd())
  360. {
  361. dependenciesBuffer.Remove(depend[i]);
  362. }
  363. }
  364. bool isShowDebug = Input.GetKeyUp(KeyCode.K);
  365. int count = 0;
  366. for (m_currLoadAsset.Begin(); m_currLoadAsset.Next();)
  367. {
  368. if (isShowDebug)
  369. {
  370. Debug.Log(m_currLoadAsset.Key.name + "____" + m_currLoadAsset.Value.HandCount);
  371. }
  372. count += m_currLoadAsset.Value.HandCount;
  373. m_currLoadAsset.Value.Update();
  374. }
  375. if (isShowDebug)
  376. {
  377. Debug.Log($"当前拥有资源数:{count} bundle数:{m_currLoadBundle.Count}");
  378. }
  379. }
  380. public void RemoveAssetTask(AssetInfo assetInfo)
  381. {
  382. if (m_currLoadAsset.ContainsKey(assetInfo))
  383. {
  384. m_currLoadAsset.Remove(assetInfo);
  385. }
  386. }
  387. public void RemoveBundleTask(BundleLoadBasic budnleLoadTask)
  388. {
  389. if (m_currLoadBundle.ContainsKey(budnleLoadTask.bundleName))
  390. {
  391. m_currLoadBundle.Remove(budnleLoadTask.bundleName);
  392. }
  393. }
  394. public void ClearUnusedBundles()
  395. {
  396. }
  397. public bool IsAssetInfo(string assetName)
  398. {
  399. return false;
  400. }
  401. }
  402. #endif