123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- namespace CommonUnity3D.XMUnity.LoadUtil
- {
- /// <summary>
- /// XMUnityAssetBundle加载管理器.
- /// </summary>
- public class XMUnityAssetBundleManager : MonoBehaviour
- {
- private static XMUnityAssetBundleManager mInstance = null;
- private Dictionary<string, XMUnityAssetBundle> mABMap = null;
- private Dictionary<string, XMUnityABLoadAdapter> mLoadTaskMap = null;
- public AssetBundleManifest Manifest { get; private set; }
- public List<Shader> ShaderList { get; private set; }
- private Dictionary<string, List<string>> mDepsList = new Dictionary<string, List<string>>();
- public int PrefabCapacity = 50;
- private bool mNeedCleanUp = false;
- private List<XMUnityABLoadAdapter> mTempLoadTask = null;
- private AsyncOperation mUnloadOp = null;
- private bool mNeedUnload = false;
- void Awake()
- {
- mInstance = this;
- Init();
- }
- void Start()
- {
- }
- void Update()
- {
- //检查加载任务
- mTempLoadTask = new List<XMUnityABLoadAdapter>(mLoadTaskMap.Values);
- var iter = mTempLoadTask.GetEnumerator();
- while (iter.MoveNext())
- {
- if(iter.Current.OnAdapterUpdate())
- {
- iter.Current.Dispose();
- mLoadTaskMap.Remove(iter.Current.GetURL());
- }
- }
- mTempLoadTask.Clear();
- //是否存在加载任务
- bool isLoading = false;
- if (mLoadTaskMap.Count == 0)
- {
- var item = mABMap.GetEnumerator();
- while (item.MoveNext())
- {
- if (item.Current.Value.BundleStatus == XMUnityAssetBundle.Status.LoadAsset || item.Current.Value.BundleStatus == XMUnityAssetBundle.Status.LoadDep)
- {
- isLoading = true;
- break;
- }
- }
- }
- else
- {
- isLoading = true;
- }
- //在合适的时候执行Cleanup
- if (!isLoading && mNeedCleanUp)
- {
- CleanAssetBundleMap(false);
- //Resources.UnloadUnusedAssets ();
- System.GC.Collect();
- mNeedCleanUp = false;
- }
- //检查unload进度
- if(mUnloadOp != null && mUnloadOp.isDone)
- {
- mUnloadOp = null;
- }
- //在合适的时候执行unload
- if (!isLoading && mNeedUnload)
- {
- mUnloadOp = Resources.UnloadUnusedAssets();
- mNeedUnload = false;
- }
- }
- private void Init()
- {
- mABMap = new Dictionary<string, XMUnityAssetBundle>();
- mLoadTaskMap = new Dictionary<string, XMUnityABLoadAdapter>();
- mTempLoadTask = new List<XMUnityABLoadAdapter>();
- ShaderList = new List<Shader>();
- StartLoadManifest();
- StartLoadShaderList();
- }
- void StartLoadManifest()
- {
- XMUnityABLoadAdapter load = new XMUnityABLoadAdapter();
- load.LoadAsync = false;
- load.SetFinishCallBack(OnManifestFinish);
- load.Load("/res/" + GetPlatformForAssetBundles(), null);
- StartCoroutine(CheckLoadManifest(load));
- }
- IEnumerator CheckLoadManifest(XMUnityABLoadAdapter load)
- {
- while (!load.HasDone)
- {
- load.OnAdapterUpdate();
- yield return null;
- }
- }
- private void OnManifestFinish(XMUnityABLoadAdapter adapter)
- {
- if (adapter.GetAssetBundle() != null)
- {
- Manifest = adapter.GetAssetBundle().LoadAsset<AssetBundleManifest>("AssetBundleManifest");
- }
- else
- {
- Debug.LogError("XMUnityAssetBundleManager can not find Manifest");
- }
- }
- void StartLoadShaderList()
- {
- XMUnityABLoadAdapter load = new XMUnityABLoadAdapter();
- load.LoadAsync = false;
- load.SetFinishCallBack(OnShaderListFinish);
- load.Load("/res/shaderslist.assetbundles", null);
- StartCoroutine(CheckLoadShaderList(load));
- }
- IEnumerator CheckLoadShaderList(XMUnityABLoadAdapter load)
- {
- while (!load.HasDone)
- {
- load.OnAdapterUpdate();
- yield return null;
- }
- }
- private void OnShaderListFinish(XMUnityABLoadAdapter adapter)
- {
- if (adapter.GetAssetBundle() != null)
- {
- Object[] shaderobject = adapter.GetAssetBundle().LoadAllAssets();
- foreach (Object sb in shaderobject)
- {
- if (sb is Shader)
- {
- ShaderList.Add((Shader)sb);
- }
- else
- {
- Debug.Log("ShaderList add dif type=" + sb.GetType());
- }
- }
- Shader.WarmupAllShaders();
- }
- else
- {
- Debug.LogWarning("XMUnityAssetBundleManager can not find ShaderList");
- }
- }
- public void Dispose()
- {
- CleanAssetBundleMap(true);
- mInstance = null;
- }
- public static XMUnityAssetBundleManager GetInstance()
- {
- if (mInstance == null)
- {
- Debug.LogError("XMUnityAssetBundleManager must create before use");
- }
- return mInstance;
- }
- public void UnloadUnusedAssets()
- {
- if(mUnloadOp == null)
- {
- mNeedUnload = true;
- }
- }
- public List<string> GetDepList(string name)
- {
- name = name.ToLower();
- string dep_key = name.ToLower().Replace("/res/", "");
- if (!mDepsList.ContainsKey(name))
- {
- string[] deps = Manifest.GetAllDependencies(dep_key);
- List<string> ds = new List<string>(deps.Length);
- for (int i = 0; i < deps.Length; i++)
- {
- if(deps[i] != "shaderslist.assetbundles")
- {
- string key = "/res/" + deps[i];
- //if (name != key)
- //{
- ds.Add(key);
- //}
- //else
- //{
- // Debug.LogError("what the fuck");
- //}
- }
- }
- mDepsList[name] = (ds);
- }
- return mDepsList[name];
- }
- public void GetAssetBundle(string name, XMUnityABLoadAdapter.XMUnityLoadAdapterCallBack callBack, bool async = true)
- {
- name = name.ToLower();
- XMUnityAssetBundle ab = null;
- XMUnityABLoadAdapter adapter = null;
- if (mABMap.TryGetValue(name, out ab)) //从AB中寻找AssetBundle.
- {
- if (callBack != null)
- {
- callBack.Invoke(ab);
- //return null;
- }
- }
- else if (mLoadTaskMap.TryGetValue(name, out adapter)) //从正在加载的map中寻找.
- {
- if (callBack != null)
- {
- adapter.AddCallBack(callBack);
- }
- //return null;
- }
- else //创建加载器.
- {
- XMUnityABLoadAdapter load = new XMUnityABLoadAdapter();
- load.LoadAsync = async;
- mLoadTaskMap.Add(name, load);
- load.SetFinishCallBack(OnAdapterFinish);
- load.Load(name, callBack);
- //return load;
- }
- //return null;
- }
- public AssetBundle GetAssetBundle(string name)
- {
- name = name.ToLower();
- XMUnityAssetBundle ret = null;
- mABMap.TryGetValue(name, out ret);
- return ret.AssetBundle;
- }
- public XMUnityAssetBundle GetXMUnityAssetBundle(string name)
- {
- name = name.ToLower();
- XMUnityAssetBundle ret = null;
- mABMap.TryGetValue(name, out ret);
- if (ret == null)
- {
- return null;
- }
- return ret;
- }
- public bool AddAssetBundle(string name, XMUnityAssetBundle ab)
- {
- if (!string.IsNullOrEmpty(name) && ab != null)
- {
- mABMap.Add(name, ab);
- return true;
- }
- Debug.Log("XMUnityAssetBundleManager AddAssetBundle Error: Invaild Data");
- return false;
- }
- /// <summary>
- /// 将remove操作push到一个队列中执行,只有当当前没有加载任务时才会触发.
- /// </summary>
- /// <param name="name"></param>
- /// <param name="isUnloadAll"></param>
- public void UnloadAssetBundle(string name, bool isUnloadAll = false, bool force = false)
- {
- XMUnityAssetBundle ab = null;
- if (mABMap.TryGetValue(name, out ab))
- {
- if (ab != null)
- {
- if(ab.BundleType == XMUnityAssetBundle.Type.DEP_ASSET)
- {
- Debug.LogError("Cant unload a dep assetbundle: " + name);
- }
- List<string> deps = GetDepList(name);
- foreach (var item in deps)
- {
- XMUnityAssetBundle mfab = null;
- if (mABMap.TryGetValue(item, out mfab))
- {
- if (mfab != null)
- {
- if (mfab.TryUnloadDep(name, isUnloadAll, force))
- {
- mABMap.Remove(item);
- }
- }
- }
- }
- UnloadAssetBundleImmediate(name, isUnloadAll, force);
- }
- }
- else
- {
- //通常只有切换场景时没有清除资源的情况下强制卸载了所有ab才会出,可以用来监控逻辑加载卸载成对的情况
- Debug.LogWarning("[策划,测试请无视]UnloadAssetBundle Error, bundle not exists: " + name);
- }
- }
- public void UnloadAssetBundleImmediate(string name, bool isUnloadAll, bool force = false)
- {
- // 内部自动处理
- XMUnityAssetBundle ab = null;
- if (mABMap.TryGetValue(name, out ab))
- {
- if (ab != null)
- {
- //TODO 销毁XMUnityAssetBundle,主要是缓存和prefab
- if (ab.Unload(isUnloadAll, force))
- {
- mABMap.Remove(name);
- }
- }
- }
- else
- {
- Debug.LogWarning("[策划,测试请无视]UnloadAssetBundleImmediate Error, bundle not exists: " + name);
- }
- }
- public void LoadDep(string name, bool loadABASync, bool loadAssetASync, XMUnityAssetBundle.LoadResCallBack callback, object userdata, string childAB)
- {
- XMUnityAssetBundleManager.GetInstance().GetAssetBundle(name, (XMUnityAssetBundle mfab) =>
- {
- if (mfab != null)
- {
- mfab.MarkAsDeps(childAB);
- }
- //else
- {
- callback(null, null, userdata, false);
- }
- }, loadABASync);
- }
- public void LoadAsset(string name, string asset, bool loadABASync, bool loadAssetASync, XMUnityAssetBundle.LoadResCallBack callback, object userdata, System.Type type = null)
- {
- GetAssetBundle(name, (XMUnityAssetBundle mfab) =>
- {
- if (mfab != null)
- {
- mfab.GetAsset(asset, loadAssetASync, callback, userdata, type);
- }
- else
- {
- callback(asset, null, userdata, false);
- }
- }, loadABASync);
- }
- public void LoadAsset(string name, bool loadABASync, bool loadAssetASync, XMUnityAssetBundle.LoadResCallBack callback, object userdata, System.Type type = null)
- {
- int starIndex = name.LastIndexOf('/') + 1;
- int length = name.Length - starIndex - ".assetbundles".Length;
- string objectName = name.Substring(starIndex, length);
- LoadAsset(name.ToLower(), objectName, loadABASync, loadAssetASync, callback, userdata, type);
- }
- public void CleanAssetBundleMap(bool isUnloadAll)
- {
- var temp = new Dictionary<string, XMUnityAssetBundle>();
- foreach (KeyValuePair<string, XMUnityAssetBundle> kvp in mABMap)
- {
- if (kvp.Value != null)
- {
- if(!kvp.Value.Unload(isUnloadAll, true))
- {
- temp.Add(kvp.Key, kvp.Value);
- }
- }
- }
- mABMap.Clear();
- mABMap = temp;
- AssetObject.ClearRefs();
- }
- public void CleanAssetBundleMapInQueue()
- {
- mNeedCleanUp = true;
- }
- private void OnAdapterFinish(XMUnityABLoadAdapter adapter)
- {
- XMUnityAssetBundle mfab = adapter.GetXMUnityAssetBundle();
- if (mfab != null)
- {
- mABMap.Add(adapter.GetURL(), mfab);
- }
- if (mLoadTaskMap.ContainsKey(adapter.GetURL()))
- {
- mLoadTaskMap.Remove(adapter.GetURL());
- }
- else
- {
- Debug.Log("XMUnityAssetBundleManager can not find Adapter");
- }
- adapter.DispatchCallBack();
- }
- public bool ContainsBundle(string name) { return mABMap.ContainsKey(name); }
- public static string GetPlatformForAssetBundles()
- {
- RuntimePlatform platform = Application.platform;
- switch (platform)
- {
- case RuntimePlatform.Android:
- return "android";
- case RuntimePlatform.IPhonePlayer:
- return "ios";
- case RuntimePlatform.WebGLPlayer:
- return "webgl";
- case RuntimePlatform.OSXWebPlayer:
- case RuntimePlatform.WindowsWebPlayer:
- return "standalonewindows";
- case RuntimePlatform.WindowsEditor:
- #if UNITY_ANDROID
- return "android";
- #else
- return "standalonewindows";
- #endif
- case RuntimePlatform.WindowsPlayer:
- return "standalonewindows";
- case RuntimePlatform.OSXPlayer:
- return "osx";
- default:
- return null;
- }
- }
- }
- }
|