AssetBundleLoadManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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.unity3d";
  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. #if UNITY_ANDROID&&!UNITY_EDITOR
  216. url = "file://" + url;
  217. #endif
  218. Debug.Log(url);
  219. UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url);
  220. webRequest.certificateHandler = new CustomCertificateHandler();
  221. UnityWebRequestAsyncOperation webRequestAsyncOperation = webRequest.SendWebRequest();
  222. // AssetBundleCreateRequest bundlReq = AssetBundle.LoadFromFileAsync(url);
  223. webRequestAsyncOperation.completed += delegate(AsyncOperation operation)
  224. {
  225. DownloadHandlerAssetBundle downloadHandler = webRequest.downloadHandler as DownloadHandlerAssetBundle;
  226. assetBundleManifest = downloadHandler.assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  227. if (assetBundleManifest != null)
  228. {
  229. LogTool.Log("AssetBundleManifest jizaiwancheng");
  230. }
  231. assetBundleHash = GetABNamesWithHash(assetBundleManifest);
  232. downloadHandler.assetBundle.Unload(false);
  233. CallBackLoadEnd();
  234. };
  235. }
  236. public string[] GetBundleDependencies(string bundleName)
  237. {
  238. if (assetBundleManifest == null)
  239. {
  240. return null;
  241. }
  242. return assetBundleManifest.GetDirectDependencies(bundleName);
  243. }
  244. public async CTask<AssetHandle> LoadAssetAsyncTask<T>(string assetName,
  245. System.Action<AssetHandle> callBack = null, Clock clock = null, bool isUseSynchronous = false) where T : Object
  246. {
  247. onLoadAsset?.Invoke(assetName);
  248. //临时使用到007的bundle加载,现在这个bundel卸载有遗漏,后面有时间了在改
  249. CTask task = CTask.Create(false);
  250. AssetHandle obj = null;
  251. LoadAssetAsync<T>(assetName, delegate(AssetHandle o, object o1)
  252. {
  253. if (o != null)
  254. {
  255. obj = o;
  256. }
  257. task.SetResult();
  258. }, clock, isUseSynchronous);
  259. await task;
  260. // TODO 暂时去掉,不知道会不会有影响
  261. // await TimerComponent.Instance.WaitFrameAsync();
  262. callBack?.Invoke(obj);
  263. return obj;
  264. }
  265. private void LoadAssetAsync<T>(string assetName, System.Action<AssetHandle, object> callBack, Clock clock = null,
  266. object userData = null, bool isUseSynchronous = false) where T : Object
  267. {
  268. if (!assetToBundleDict.TryGetValue(assetName, out AssetInfo assetInfo))
  269. {
  270. callBack?.Invoke(null, userData);
  271. Debug.LogWarning("没找到资源" + assetName);
  272. return;
  273. }
  274. LoadAssetCallBackData loadAssetCallBackData = new LoadAssetCallBackData();
  275. loadAssetCallBackData.loadEndCallBack = callBack;
  276. loadAssetCallBackData.userData = userData;
  277. loadAssetCallBackData.Clock = clock;
  278. loadAssetCallBackData.isUseSynchronous = isUseSynchronous;
  279. AssetLoadTaskBasic assetLoad = null;
  280. if (!m_currLoadAsset.TryGetValue(assetInfo, out assetLoad))
  281. {
  282. assetLoad = CreateAssetTaskBasic();
  283. assetLoad.InitAsset<T>(assetInfo, UnloadType, loadAssetCallBackData);
  284. m_currLoadAsset.Add(assetInfo, assetLoad);
  285. }
  286. else
  287. {
  288. assetLoad.AddCallBack<T>(loadAssetCallBackData);
  289. }
  290. }
  291. protected AssetLoadTaskBasic CreateAssetTaskBasic()
  292. {
  293. switch (BundleLoadType)
  294. {
  295. case BundleLoadType.LocalAsset:
  296. return new LocalAssetLoadTask();
  297. break;
  298. case BundleLoadType.LocalBundle:
  299. return new BundleAssetLoadTask();
  300. break;
  301. case BundleLoadType.H5:
  302. return new BundleAssetLoadTask();
  303. break;
  304. }
  305. LogTool.Error("加载模式不存在" + BundleLoadType);
  306. return null;
  307. }
  308. protected BundleLoadBasic CreateBundleTaskBasic()
  309. {
  310. switch (BundleLoadType)
  311. {
  312. case BundleLoadType.LocalAsset:
  313. break;
  314. case BundleLoadType.LocalBundle:
  315. return new LocalBundleLoadTask();
  316. break;
  317. case BundleLoadType.H5:
  318. return new H5BundleLoadTask();
  319. break;
  320. }
  321. LogTool.Error("加载模式不存在" + BundleLoadType);
  322. return null;
  323. }
  324. public BundleLoadBasic AddBundleTask(string bundleName, System.Action<BundleLoadBasic, object> callBack,
  325. LoadTaskBasic loadTaskBasic)
  326. {
  327. BundleLoadBasic bundleLoadTask = null;
  328. if (assetBundleHash.TryGetValue(bundleName, out string hash))
  329. {
  330. bundleName = hash;
  331. }
  332. if (m_currLoadBundle.ContainsKey(bundleName))
  333. {
  334. bundleLoadTask = m_currLoadBundle[bundleName];
  335. }
  336. if (bundleLoadTask == null)
  337. {
  338. bundleLoadTask = CreateBundleTaskBasic();
  339. //AssetInfo bundleInfo = assetToBundleDict[assetName];
  340. m_currLoadBundle.Add(bundleName, bundleLoadTask);
  341. bundleLoadTask.InitBundle(bundleName, UnloadType, callBack);
  342. bundleLoadTask.AddOwnTask(loadTaskBasic);
  343. }
  344. else
  345. {
  346. bundleLoadTask.AddOwnTask(loadTaskBasic);
  347. bundleLoadTask.AddCallBack(callBack);
  348. }
  349. return bundleLoadTask;
  350. }
  351. public string GetBudnleInfo()
  352. {
  353. return $"当前拥有资源数:{m_currLoadAsset.Count} bundle数:{m_currLoadBundle.Count}";
  354. }
  355. public void UpdateBundle()
  356. {
  357. if (stopUpdate)
  358. return;
  359. BundleLoadBasic[] depend = dependenciesBuffer.ToArray();
  360. for (int i = 0; i < depend.Length; i++)
  361. {
  362. if (depend[i].AwaitDependenceLoadEnd())
  363. {
  364. dependenciesBuffer.Remove(depend[i]);
  365. }
  366. }
  367. // bool isShowDebug = Input.GetKeyUp(KeyCode.K);
  368. int count = 0;
  369. for (m_currLoadAsset.Begin(); m_currLoadAsset.Next();)
  370. {
  371. // if (isShowDebug)
  372. // {
  373. // Debug.Log(m_currLoadAsset.Key.name + "____" + m_currLoadAsset.Value.HandCount);
  374. // }
  375. count += m_currLoadAsset.Value.HandCount;
  376. m_currLoadAsset.Value.Update();
  377. }
  378. // if (isShowDebug)
  379. // {
  380. // Debug.Log($"当前拥有资源数:{count} bundle数:{m_currLoadBundle.Count}");
  381. // }
  382. }
  383. public void RemoveAssetTask(AssetInfo assetInfo)
  384. {
  385. if (m_currLoadAsset.ContainsKey(assetInfo))
  386. {
  387. m_currLoadAsset.Remove(assetInfo);
  388. }
  389. }
  390. public void RemoveBundleTask(BundleLoadBasic budnleLoadTask)
  391. {
  392. if (m_currLoadBundle.ContainsKey(budnleLoadTask.bundleName))
  393. {
  394. m_currLoadBundle.Remove(budnleLoadTask.bundleName);
  395. }
  396. }
  397. public void ClearUnusedBundles()
  398. {
  399. }
  400. public bool IsAssetInfo(string assetName)
  401. {
  402. return false;
  403. }
  404. }
  405. #endif