using System; using System.Collections; using System.Collections.Generic; using System.IO; using Common.Event; using UnityEngine; using SandboxMap.Data; using Object = UnityEngine.Object; public enum AssetBundleType { WoldMap, Construction, UI, NPC, //NPC模型的组件 NPCModel,//若干AB组件结合成的NPC模型,3D人物模型 FILMSCENE,//电影场景 } /// <summary> /// 资源加载工具 /// </summary> public class AssetBundleTool : MonoManagerBase<AssetBundleTool> { /// <summary> /// 预加载资源 /// </summary> public void ReadyLoad() { ReadyLoadAsset = new List<string>(); _elapsedTime = 0; StartCoroutine(ElapsedTimeEnumer()); AddReadyLoadAsset("labelpanel", AssetBundleType.UI); AddReadyLoadAsset("commen_npc", AssetBundleType.NPC); AddReadyLoadAsset("commen_construction", AssetBundleType.Construction); AddReadyLoadAsset("StoryDialoguePanel", AssetBundleType.UI); AddReadyLoadAsset("TaskReceiveWindow", AssetBundleType.UI); AddReadyLoadAsset("TaskCommitWindow", AssetBundleType.UI); ReadyLoadBuild(); Debug.Log("******AssetBundleReadyLoadAssetCount*******" + ReadyLoadAsset.Count); } /// <summary> /// 资源更新完成后 预加载 /// </summary> public void PreLoad() { LoadResourceAsync<Font>("Font", AssetBundleType.UI, "DENG"); } private float _elapsedTime; private List<string> ReadyLoadAsset; private void AddReadyLoadAsset(string data,AssetBundleType type) { data = data.ToLower(); ReadyLoadAsset.Add(data); LoadResource(data, type, null); } public void ReadyLoadEnd(string data) { if (ReadyLoadAsset == null) return; if (ReadyLoadAsset.Contains(data)) { ReadyLoadAsset.Remove(data); } else { Debug.Log("不在预加载集合中*********" + data); } if (ReadyLoadAsset.Count == 0) { ReadyLoadAsset = null; GameManager.Instance.ToStartGame(); Debug.Log("******AssetBundleReadyLoadAssetEnd*******ElapsedTime:" + _elapsedTime); } } private IEnumerator ElapsedTimeEnumer() { while (ReadyLoadAsset != null) { _elapsedTime += Time.deltaTime; yield return 1; } } /// <summary> /// 预加载建筑 /// </summary> /// <param name="data"></param> private void ReadyLoadBuild() { BuildingConfigData data = ConfigManager.Instance.load<global::BuildingConfigData>(); if (data == null || data.datas == null) return; for (int i = 0; i < data.datas.Length; i++) { ConstructionConfig building = data.datas[i]; AddReadyLoadAsset(building.modeID + "_" + building.level , AssetBundleType.Construction); } } /* /// <summary> /// 同步获得资源 /// </summary> /// <param name="data"></param> /// <param name="type"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public GameObject GetReadyObject(string data, AssetBundleType type) { string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + data + ".data"; try { return AssetTool.GetAssetByName<GameObject>(ResourcesDic[resUrl],data) as GameObject; } catch (Exception e) { throw new Exception(data + ":没有做预加载" + e.Message); } } */ private EventDispatcher _eventManager; public EventDispatcher EventManager => _eventManager; private Queue<Dependence> _dependences; /// <summary> /// 依赖资源 /// </summary> private List<string> DependencesList; /// <summary> /// 资源缓存字典 /// </summary> public Dictionary<string, UnityEngine.Object[]> AssetsDic; public bool CheckAssetsContains(string url) { if (AssetsDic!=null && AssetsDic.ContainsKey(url)) { return true; } return false; } public void AddAssets2Dic(string key,UnityEngine.Object[] assets) { if (AssetsDic == null) { AssetsDic=new Dictionary<string, UnityEngine.Object[]>(); } if (AssetsDic.ContainsKey(key)) { Debug.LogError("已存在ResourcesDic*********" + key + "*********" + assets); } else { AssetsDic.Add(key, assets); } } public Object[] GetAssets(string key) { if (AssetsDic != null && AssetsDic.ContainsKey(key)) { return AssetsDic[key]; } return null; } /// <summary> /// 正在加载中 /// </summary> public List<string> InLoadResources; private AssetBundleManifest _woldMapManifest; // private AssetBundleManifest _constructionManifest; private AssetBundleManifest _uiManifest; private AssetBundleManifest _npcManifest; private string PATHRESROOTDIR; public void unload(string assetBundleName, AssetBundleType type = AssetBundleType.UI) { assetBundleName = assetBundleName.ToLower(); string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + assetBundleName + ".data"; UnityEngine.Object[] ress = GetAssets(resUrl); AssetsDic.Remove(resUrl); Resources.UnloadUnusedAssets(); GC.Collect(); } /// <summary> /// 加载item方便实用 /// </summary> /// <param name="assetBundleName"></param> /// <param name="type"></param> /// <param name="assetName"></param> /// <returns></returns> public RectTransform Load(string assetBundleName, string assetName = "") { GameObject asset = LoadResource<GameObject>(assetBundleName, AssetBundleType.UI, assetName); return Instantiate(asset).transform as RectTransform; } /// <summary> /// 同步加载 /// </summary> /// <param name="assetBundleName"></param> /// <param name="type"></param> /// <param name="back"></param> /// <param name="assetName"></param> /// <returns></returns> public T LoadResource<T>(string assetBundleName, AssetBundleType type, string assetName = "") where T : UnityEngine.Object { assetBundleName = assetBundleName.ToLower(); assetName = assetName.ToLower(); string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + assetBundleName + ".data"; if (string.IsNullOrEmpty(assetName)) assetName = assetBundleName; if (CheckAssetsContains(resUrl)) { return AssetTool.GetAsset<T>(GetAssets(resUrl), assetName) as T; } else { AssetBundle ab = null; ab = AssetBundle.LoadFromFile(resUrl); if (ab == null) { Debug.LogError("文件不存在! fileName : " + resUrl); return null; } UnityEngine.Object[] assets = ab.LoadAllAssets(); AddAssets2Dic(resUrl, assets); T obj = AssetTool.GetAsset<T>(assets,assetName) as T; ab.Unload(false); return obj; } } public void LoadSceneAsync(string assetBundleName, AssetBundleType type, Action action) { StartCoroutine(LoadSceneAsyncFun(assetBundleName, type, action)); } private IEnumerator LoadSceneAsyncFun(string assetBundleName, AssetBundleType type, Action action) { assetBundleName = assetBundleName.ToLower(); string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + assetBundleName + ".data"; if (CheckAssetsContains(resUrl) && action != null) { action(); } else { AssetBundleCreateRequest abReq; AssetBundle ab = null; abReq = AssetBundle.LoadFromFileAsync(resUrl); yield return abReq; ab = abReq.assetBundle; if (ab == null) { Debug.LogError("文件不存在! fileName : " + resUrl); if (action != null) action(); } if (ab.isStreamedSceneAssetBundle) { AddAssets2Dic(resUrl, new Object[] { ab }); if (action != null) action(); yield break; } if (action != null) action(); } } /// <summary> /// 资源异步加载,返回Asset资源 /// </summary> /// <param name="assetBundleName">包名</param> /// <param name="type">资源类型</param> /// <param name="assetName">在包中的资源名</param> /// <param name="action">加载完成后的回调函数</param> /// <param name="save">是否需要在内存中保留assetBundle镜像资源</param> /// <typeparam name="T"></typeparam> public void LoadResourceAsync<T>(string assetBundleName, AssetBundleType type, string assetName = "", Action<T> action = null,bool save = true) where T : UnityEngine.Object { StartCoroutine(LoadResourceAsyncFun(assetBundleName, type, assetName, action, save)); } private IEnumerator LoadResourceAsyncFun<T>(string assetBundleName, AssetBundleType type, string assetName, Action<T> action,bool save) where T : UnityEngine.Object { assetBundleName = assetBundleName.ToLower(); assetName = assetName.ToLower(); string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + assetBundleName + ".data"; string key = resUrl + assetName; if (CheckAssetsContains(key) && action != null) { Object obj = AssetTool.GetAsset<T>(GetAssets(resUrl), assetBundleName); if (obj is T) { action(obj as T); } else if (obj is AssetBundle) { action(null); } } else { AssetBundleCreateRequest abReq; AssetBundle ab = null; abReq = AssetBundle.LoadFromFileAsync(resUrl); yield return abReq; ab = abReq.assetBundle; if (ab == null) { Debug.LogError("文件不存在! fileName : " + resUrl); if(action != null) action(null); } if (string.IsNullOrEmpty(assetName)) assetName = assetBundleName; if(ab.isStreamedSceneAssetBundle) { AddAssets2Dic(resUrl, new Object[] { ab }); if (action != null) action(null); yield break; } AssetBundleRequest assets = ab.LoadAllAssetsAsync(); yield return assets; AddAssets2Dic(resUrl,assets.allAssets); T obj = AssetTool.GetAsset<T>(assets.allAssets,assetName) as T; if (!save) { ab.Unload(false); } if (action != null) action(obj); } } /// <summary> /// 根据name加载一个预设文件,设置为parent的子物体 -- 异步 -- /// </summary> public void LoadResource(string data, AssetBundleType type, Action<GameObject> back) { data = data.ToLower(); if (_eventManager == null) { _eventManager = new EventDispatcher(); _eventManager.AddEventListener(AssetBundleEventType.LoadEnd, LoadEvent); _dependences = new Queue<Dependence>(); DependencesList = new List<string>(); InLoadResources = new List<string>(); } StartCoroutine(Load(data, type, back)); } private IEnumerator Load(string data, AssetBundleType type, Action<GameObject> back) { string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + data + ".data"; while (InLoadResources.Contains(resUrl)) { yield return 1; } if (CheckAssetsContains(resUrl)) { _eventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); GameObject obj = AssetTool.GetAsset<GameObject>(GetAssets(resUrl), data) as GameObject; back?.Invoke(obj); yield break; } if (!File.Exists(resUrl)) { Debug.LogWarning("文件不存在: " + resUrl); ReadyLoadEnd(data); _eventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); back?.Invoke(null); yield break; } InLoadResources.Add(resUrl); AssetBundleManifest manifest = null; switch (type) { case AssetBundleType.WoldMap: if (_woldMapManifest != null) manifest = _woldMapManifest; break; case AssetBundleType.Construction: if (_constructionManifest != null) manifest = _constructionManifest; break; case AssetBundleType.UI: if (_uiManifest != null) manifest = _uiManifest; break; case AssetBundleType.NPC: if (_npcManifest != null) manifest = _npcManifest; break; } if (manifest == null) { string manifestPath = Path.Combine(ClientInfo.DataPath + "/AssetBundleDatas/", type.ToString()); manifestPath = Path.Combine(manifestPath, type.ToString()); // if (!File.Exists(manifestPath)) // { // _eventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); // back?.Invoke(null); // } AssetBundle asset = AssetBundle.LoadFromFile(manifestPath); manifest = asset.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); switch (type) { case AssetBundleType.WoldMap: _woldMapManifest = manifest; break; case AssetBundleType.Construction: _constructionManifest = manifest; break; case AssetBundleType.UI: _uiManifest = manifest; break; case AssetBundleType.NPC: _npcManifest = manifest; break; } asset.Unload(false); } Dependence dep = new Dependence(data, type.ToString(), manifest, back); _dependences.Enqueue(dep); if (_isFrist) { _isFrist = false; _eventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); } } private bool _isFrist = true; private void LoadEvent(GameEventArgs e) { if (_dependences.Count > 0) { _dependences.Dequeue().Init(); } else { _isFrist = true; } } public bool GetDepContain(string key) { if (!DependencesList.Contains(key)) { DependencesList.Add(key); return false; } return true; } public void LoadScene(string sceneName, Action action) { StartCoroutine(LoadSceneFun(sceneName, action)); } private IEnumerator LoadSceneFun(string sceneName, Action action) { sceneName = sceneName.ToLower(); string resUrl = ClientInfo.DataPath + "/AssetBundleDatas/WorldMap/" + sceneName + ".data"; string key = resUrl; if (CheckAssetsContains(key) && action != null) { action(); } else { AssetBundleCreateRequest abReq; AssetBundle ab = null; abReq = AssetBundle.LoadFromFileAsync(resUrl); yield return abReq; /* ab = abReq.assetBundle; if (ab == null) { Debug.LogError("文件不存在! fileName : " + resUrl); if(action != null) action(); } AssetBundleRequest assets = SceneManager.LoadScene() yield return assets; AddAssets2Dic(resUrl,assets.allAssets); ab.Unload(false); */ if (action != null) action(); } } } public static class AssetBundleEventType { public const string LoadEnd = "LOADEND"; } public class Dependence { private readonly string _data; private readonly string _url; private readonly string _type; private readonly AssetBundleManifest _manifest; private readonly Action<GameObject> _back; public Dependence(string data, string type, AssetBundleManifest manifest, Action<GameObject> back) { _data = data; _url = ClientInfo.DataPath + "/AssetBundleDatas/" + type + "/" + data + ".data"; _type = type; _manifest = manifest; _back = back; } public void Init() { AssetBundleTool.instance.StartCoroutine(LoadDependences()); } /// <summary> /// 加载依赖项 /// </summary> /// <returns></returns> private IEnumerator LoadDependences() { AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(_url); yield return request; if (string.Equals(_data, "commen_npc") || string.Equals(_data, "commen_construction")) { AssetBundleTool.instance.ReadyLoadEnd(_data); AssetBundleTool.instance.EventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); yield break; } AssetBundle assetBundle = request.assetBundle; if (assetBundle == null) { Debug.LogError("SceneProp assetsBundle is null! fileName : " + _url); yield break; } AssetBundleRequest result = assetBundle.LoadAllAssetsAsync(); yield return result; object temp = AssetTool.GetAsset<GameObject>(result.allAssets,_data); UnityEngine.Object obj = temp as UnityEngine.Object; _back?.Invoke(obj as GameObject); AssetBundleTool.instance.ReadyLoadEnd(_data); AssetBundleTool.instance.AddAssets2Dic(_url, result.allAssets); AssetBundleTool.instance.InLoadResources.Remove(_url); AssetBundleTool.instance.EventManager.DispatchEvent(new GameEventArgs(AssetBundleEventType.LoadEnd)); if(_type == "Construction" || _type == "NPC") { assetBundle.Unload(false); } } } public class AssetTool { public static UnityEngine.Object GetAsset<T>(UnityEngine.Object[] assets, string name) { UnityEngine.Object temp = null; for (int i = 0; i < assets.Length; i++) { temp = assets[i]; if (temp is T) { string nameValue = temp.ToString(); string tempName = nameValue.Substring(0, nameValue.IndexOf(" ")).ToLower(); if (tempName == name) { //Debug.Log(tempName); return temp; } } } return null; } public static T[] GetAssetAll<T>(UnityEngine.Object[] assets) { List<T> tempResult= new List<T>(); System.Object temp = null; for (int i = 0; i < assets.Length; i++) { temp = assets[i]; if (temp is T) { //Debug.Log(temp); tempResult.Add((T)temp); } } return tempResult.ToArray(); } }
Unity AssetBundle加载
最新推荐文章于 2025-01-12 00:00:35 发布