using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using Core.AssetLoadTool.Asset; using Fort23.Core; using Fort23.UTool; #if !COMBAT_SERVER using UnityEngine; using UnityEngine.Networking; using Object = UnityEngine.Object; using Utility; public class AssetBundleLoadManager : Singleton { public BundleLoadType BundleLoadType; public string h5Url; public bool UnloadType = true; public bool stopUpdate; private string m_rootStreamingURL; public string RootStreamingURL { get { return m_rootStreamingURL; } } private string m_rootStreamingBundleURL; public string RootStreamingBundleURL { get { return m_rootStreamingBundleURL; } } private string m_rootPersistentBundleURL; public string RootPersistentBundleURL { get { return m_rootPersistentBundleURL; } } public string manifestName { get { return m_manifestName; } } private string m_manifestName; private string m_globalConfigName; private string m_buildNoName; private string m_assetConfigName; public float gcTime; public Map assetToBundleDict = new Map(); private AssetBundleManifest assetBundleManifest = null; private Dictionary assetBundleHash = new Dictionary(); private int index = 0; private System.Action loadEndCallBack; public Map m_currLoadAsset = new Map(); public Map m_currLoadBundle = new Map(); public bool isSceneLoad; private List bundleUnloadBuffer = new List(); public List dependenciesBuffer = new List(); public bool isUnload; public System.Action onLoadAsset; public AssetBundleLoadManager() { SetFileRoot(); } public async CTask InitAssetsManager(System.Action loadEndCallBack) { // Ctask CTask cTask = CTask.Create(false); LogTool.Log("kaishijiazai asset"); this.loadEndCallBack = delegate { cTask.SetResult(); loadEndCallBack?.Invoke(); }; index = 0; //Load assetconfig file. LoadAssetConfig(null); //Load manifest file. LoadManifest(); await cTask; } public void UnloadBundleBuffer() { LogTool.Log("卸载数据"); for (int i = 0; i < bundleUnloadBuffer.Count; i++) { bundleUnloadBuffer[i].UnloadBundle(); } bundleUnloadBuffer.Clear(); } public void CallBackLoadEnd() { index++; if (index >= 2) { loadEndCallBack(); } } private void SetFileRoot() { m_rootStreamingURL = Application.streamingAssetsPath; m_rootStreamingBundleURL = m_rootStreamingURL + "/Bundle/"; m_rootPersistentBundleURL = Application.persistentDataPath + "/Bundle/"; #if UNITY_EDITOR m_assetConfigName = Application.streamingAssetsPath + "/assetConfig.txt"; #elif UNITY_IPHONE m_rootStreamingURL = "file://" + m_rootStreamingURL; m_rootStreamingBundleURL = "file://" + m_rootStreamingBundleURL; m_assetConfigName = m_rootPersistentBundleURL + "assetConfig.txt"; #else m_assetConfigName = m_rootPersistentBundleURL + "assetConfig.txt"; #endif m_manifestName = "UnityBundle.unity3d"; //Temp path. When version update is ready, path will be persistentPath and streamingPath. // m_rootpersistentBundleURL = Application.persistentDataPath + "/BundlAsset/"; } private Dictionary GetABNamesWithHash(AssetBundleManifest abm) { var hashNames = abm.GetAllAssetBundles(); Dictionary ABNamesDict = new Dictionary(); foreach (var hashName in hashNames) { //需要注意AB后缀名,默认 .unity3d var abName = Regex.Match(hashName, "_[0-9a-f]{32}").Success ? hashName.Substring(0, hashName.Length - 33) : hashName; ABNamesDict.Add(abName, hashName); } return ABNamesDict; } public void LoadAssetConfig(System.Action callBack) { DoLoadingAssetConfig(m_assetConfigName, callBack); } private void DoLoadingAssetConfig(string url, System.Action callBack) { assetToBundleDict.Clear(); if (BundleLoadType != BundleLoadType.H5 && File.Exists(url)) { Debug.Log("URL:" + url); string data = File.ReadAllText(url); LoadPackedInfo(data, callBack); } else { // url = m_rootStreamingURL + if (BundleLoadType != BundleLoadType.H5) { url = m_rootStreamingBundleURL + "assetConfig.txt"; } else { url = h5Url + "assetConfig.txt"; } Debug.Log("URL22:" + url); Uri uri = new Uri(url); UnityWebRequest unityWebRequest = UnityWebRequest.Get(uri); unityWebRequest.SetRequestHeader("Content-Type", "application/json"); unityWebRequest.SetRequestHeader("Accept", "application/json"); unityWebRequest.certificateHandler = new CustomCertificateHandler(); UnityWebRequestAsyncOperation webRequestAsyncOperation = unityWebRequest.SendWebRequest(); webRequestAsyncOperation.completed += delegate(AsyncOperation operation) { if (!string.IsNullOrEmpty(webRequestAsyncOperation.webRequest.downloadHandler.error)) { LogTool.Error(Application.streamingAssetsPath + "m_assetConfigName buchunzai" + m_assetConfigName); LogTool.Error(webRequestAsyncOperation.webRequest.downloadHandler.error); } else { LoadPackedInfo(webRequestAsyncOperation.webRequest.downloadHandler.text, callBack); } }; } return; } private void LoadPackedInfo(string json, System.Action callBack) { // Debug.Log(json); AllPackedAssetsInfo allPackedInfo = JsonManager.FromJson(json); Debug.Log(allPackedInfo != null); Debug.Log(allPackedInfo.assetsList.Count); for (int i = 0; i < allPackedInfo.assetsList.Count; i++) { AssetInfo assetInfo = allPackedInfo.assetsList[i]; if (assetInfo != null) { assetToBundleDict.Add(assetInfo.name, assetInfo); } } if (callBack != null) callBack(); CallBackLoadEnd(); } private void LoadManifest() { DoLoadingManifest(); } private void DoLoadingManifest() { string url = RootPersistentBundleURL + m_manifestName; if (BundleLoadType != BundleLoadType.H5 && !File.Exists(url)) { url = Application.streamingAssetsPath + "/Bundle/" + m_manifestName; } if (BundleLoadType == BundleLoadType.LocalAsset) { CallBackLoadEnd(); return; } if (BundleLoadType == BundleLoadType.H5) { url = h5Url + m_manifestName; } #if UNITY_ANDROID&&!UNITY_EDITOR url = "file://" + url; #endif Debug.Log(url); UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url); webRequest.certificateHandler = new CustomCertificateHandler(); UnityWebRequestAsyncOperation webRequestAsyncOperation = webRequest.SendWebRequest(); // AssetBundleCreateRequest bundlReq = AssetBundle.LoadFromFileAsync(url); webRequestAsyncOperation.completed += delegate(AsyncOperation operation) { DownloadHandlerAssetBundle downloadHandler = webRequest.downloadHandler as DownloadHandlerAssetBundle; assetBundleManifest = downloadHandler.assetBundle.LoadAsset("AssetBundleManifest"); if (assetBundleManifest != null) { LogTool.Log("AssetBundleManifest jizaiwancheng"); } assetBundleHash = GetABNamesWithHash(assetBundleManifest); downloadHandler.assetBundle.Unload(false); CallBackLoadEnd(); }; } public string[] GetBundleDependencies(string bundleName) { if (assetBundleManifest == null) { return null; } return assetBundleManifest.GetDirectDependencies(bundleName); } public async CTask LoadAssetAsyncTask(string assetName, System.Action callBack = null, Clock clock = null, bool isUseSynchronous = false) where T : Object { onLoadAsset?.Invoke(assetName); //临时使用到007的bundle加载,现在这个bundel卸载有遗漏,后面有时间了在改 CTask task = CTask.Create(false); AssetHandle obj = null; LoadAssetAsync(assetName, delegate(AssetHandle o, object o1) { if (o != null) { obj = o; } task.SetResult(); }, clock, isUseSynchronous); await task; // TODO 暂时去掉,不知道会不会有影响 // await TimerComponent.Instance.WaitFrameAsync(); callBack?.Invoke(obj); return obj; } private void LoadAssetAsync(string assetName, System.Action callBack, Clock clock = null, object userData = null, bool isUseSynchronous = false) where T : Object { if (!assetToBundleDict.TryGetValue(assetName, out AssetInfo assetInfo)) { callBack?.Invoke(null, userData); Debug.LogWarning("没找到资源" + assetName); return; } LoadAssetCallBackData loadAssetCallBackData = new LoadAssetCallBackData(); loadAssetCallBackData.loadEndCallBack = callBack; loadAssetCallBackData.userData = userData; loadAssetCallBackData.Clock = clock; loadAssetCallBackData.isUseSynchronous = isUseSynchronous; AssetLoadTaskBasic assetLoad = null; if (!m_currLoadAsset.TryGetValue(assetInfo, out assetLoad)) { assetLoad = CreateAssetTaskBasic(); assetLoad.InitAsset(assetInfo, UnloadType, loadAssetCallBackData); m_currLoadAsset.Add(assetInfo, assetLoad); } else { assetLoad.AddCallBack(loadAssetCallBackData); } } protected AssetLoadTaskBasic CreateAssetTaskBasic() { switch (BundleLoadType) { case BundleLoadType.LocalAsset: return new LocalAssetLoadTask(); break; case BundleLoadType.LocalBundle: return new BundleAssetLoadTask(); break; case BundleLoadType.H5: return new BundleAssetLoadTask(); break; } LogTool.Error("加载模式不存在" + BundleLoadType); return null; } protected BundleLoadBasic CreateBundleTaskBasic() { switch (BundleLoadType) { case BundleLoadType.LocalAsset: break; case BundleLoadType.LocalBundle: return new LocalBundleLoadTask(); break; case BundleLoadType.H5: return new H5BundleLoadTask(); break; } LogTool.Error("加载模式不存在" + BundleLoadType); return null; } public BundleLoadBasic AddBundleTask(string bundleName, System.Action callBack, LoadTaskBasic loadTaskBasic) { BundleLoadBasic bundleLoadTask = null; if (assetBundleHash.TryGetValue(bundleName, out string hash)) { bundleName = hash; } if (m_currLoadBundle.ContainsKey(bundleName)) { bundleLoadTask = m_currLoadBundle[bundleName]; } if (bundleLoadTask == null) { bundleLoadTask = CreateBundleTaskBasic(); //AssetInfo bundleInfo = assetToBundleDict[assetName]; m_currLoadBundle.Add(bundleName, bundleLoadTask); bundleLoadTask.InitBundle(bundleName, UnloadType, callBack); bundleLoadTask.AddOwnTask(loadTaskBasic); } else { bundleLoadTask.AddOwnTask(loadTaskBasic); bundleLoadTask.AddCallBack(callBack); } return bundleLoadTask; } public string GetBudnleInfo() { return $"当前拥有资源数:{m_currLoadAsset.Count} bundle数:{m_currLoadBundle.Count}"; } public void UpdateBundle() { if (stopUpdate) return; BundleLoadBasic[] depend = dependenciesBuffer.ToArray(); for (int i = 0; i < depend.Length; i++) { if (depend[i].AwaitDependenceLoadEnd()) { dependenciesBuffer.Remove(depend[i]); } } // bool isShowDebug = Input.GetKeyUp(KeyCode.K); int count = 0; for (m_currLoadAsset.Begin(); m_currLoadAsset.Next();) { // if (isShowDebug) // { // Debug.Log(m_currLoadAsset.Key.name + "____" + m_currLoadAsset.Value.HandCount); // } count += m_currLoadAsset.Value.HandCount; m_currLoadAsset.Value.Update(); } // if (isShowDebug) // { // Debug.Log($"当前拥有资源数:{count} bundle数:{m_currLoadBundle.Count}"); // } } public void RemoveAssetTask(AssetInfo assetInfo) { if (m_currLoadAsset.ContainsKey(assetInfo)) { m_currLoadAsset.Remove(assetInfo); } } public void RemoveBundleTask(BundleLoadBasic budnleLoadTask) { if (m_currLoadBundle.ContainsKey(budnleLoadTask.bundleName)) { m_currLoadBundle.Remove(budnleLoadTask.bundleName); } } public void ClearUnusedBundles() { } public bool IsAssetInfo(string assetName) { return false; } } #endif