AssetBundleLoadManager.cs 14 KB

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