using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UEObject = UnityEngine.Object; namespace BF { public class ResourceManager : ManagerBase { static ResourceManager instance; public static ResourceManager Create() { BFLog.LogAssert(instance == null, "This method only allows BFMain to call once"); instance = new ResourceManager(); return instance; } // 单个资源加载时间消耗上限.单位 s unity内部的ab加载可能也做了队列,超时先设高点,避免同时加载多个容易超时 public const float TIME_OUT_LOAD = 30f; // 资源卸载延迟时间 public const float TIME_DELAY_UNLOAD = 2f; public AssetBundleConfigCollection AbConfigCollection { get; private set; } public AssetBundleManifest Manifest { get; private set; } public override void Destroy() { instance = null; } public void Clear() { var assetList = assets.Values.ToList(); var count = assetList.Count; for (int i = count - 1; i >= 0; i--) { while (assetList[i].RefCount > 0) { Unload(assetList[i].AssetPath, true); } } assets.Clear(); AssetBundleObject.fullpathDict.Clear(); loader.Clear(); } //资源缓存 private Dictionary assets = new Dictionary(); private LoaderBase loader; private ResourceManager() { } public override void Init() { #if UNITY_EDITOR #if USE_AB loader = new AssetBundleLoader(); #else loader = new AssetLoader(); #endif #else loader = new AssetBundleLoader(); #endif } /// /// 设置资源配置 /// public void SetAbConfigCollection(AssetBundleConfigCollection abcc) { AbConfigCollection = abcc; AssetBundleObject.fullpathDict.Clear(); } public void ReloadManifest() { #if USE_AB if (Manifest != null) { Resources.UnloadAsset(Manifest); Manifest = null; } var persistentPath = System.IO.Path.Combine(Application.persistentDataPath, "update", "asset_bundle_manifest.ab"); AssetBundle assetBundle; if (System.IO.File.Exists(persistentPath)) { BFLog.Log("加载manifest " + persistentPath); assetBundle = AssetBundle.LoadFromFile(persistentPath); } else { var streamPath = System.IO.Path.Combine(Application.streamingAssetsPath, "asset_bundle_manifest.ab"); BFLog.Log("加载manifest " + streamPath); assetBundle = AssetBundle.LoadFromFile(streamPath); if (assetBundle == null) { BFLog.LogError("assetbundlemainfest is null! persistentpath : {0}, streamPath : {1}", persistentPath, streamPath); return; } } Manifest = assetBundle.LoadAsset("AssetBundleManifest"); assetBundle.Unload(false); #endif } public uint LoadAsync(string assetPath, Type type, Action complete) { if (string.IsNullOrEmpty(assetPath) || type == null || complete == null) { return 0; } BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] LoadAsync : {0}, type : {1}", assetPath, type.ToString()); if (assets.TryGetValue(assetPath, out AssetObject assetObj)) { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] LoadAsync : {0}, type : {1}. Already Complete!", assetPath, type.ToString()); if (EAssetLoadStatus.Unloading == assetObj.LoadStatus) { assetObj.LoadStatus = EAssetLoadStatus.Complete; } else if (EAssetLoadStatus.Error == assetObj.LoadStatus) //出错的资源,尝试重新加载 { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] assetpath : {0} 上次加载出错了,重新加载", assetPath); loader.LoadAssetAsync(assetObj); } assetObj.LoadAsync(complete); } else { assetObj = loader.LoadAssetAsync(assetPath, type, complete); assets.Add(assetPath, assetObj); assetObj.LoadAsync(complete); } return assetObj.Id; } /// /// 此接口需要多测试!!!尝试unity2018的api。可以直接从异步接口中返回同步值,从而从把异步变成同步 /// /// /// /// public UEObject LoadSync(string assetPath, Type type) { if (string.IsNullOrEmpty(assetPath) || type == null) { return null; } if (assets.TryGetValue(assetPath, out AssetObject assetObj)) { if (EAssetLoadStatus.Error == assetObj.LoadStatus) //出错的资源,尝试重新加载 { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] assetpath : {0} 上次加载出错了,重新加载", assetPath); loader.LoadAssetSync(assetObj); } else if (EAssetLoadStatus.Wait == assetObj.LoadStatus) { loader.LoadAssetSync(assetObj); } assetObj.LoadSync(); } else { assetObj = loader.LoadAssetSync(assetPath, type); assetObj.LoadSync(); assets.Add(assetPath, assetObj); } return assetObj.Asset; } public void Unload(string assetPath, bool immediately) { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] Unload assetpath : {0}", assetPath); if (string.IsNullOrEmpty(assetPath)) { return; } if (!assets.TryGetValue(assetPath, out AssetObject ao)) { return; } loader.Unload(ao, immediately); } public void Unload(AssetObject assetObject, bool immediately) { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] Unload assetObject : {0}", assetObject); if (assetObject == null) { return; } loader.Unload(assetObject, immediately); } public void RemoveAsset(string assetPath) { BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] RemoveAsset assetPath : {0}", assetPath); if (assets.ContainsKey(assetPath)) { assets.Remove(assetPath); } } public void UnloadAllDelayAssets() { loader.UnloadAllDelayAssets(); } public string GetSceneLoadPath(string assetBundlePath) { return loader.GetSceneLoadPath(assetBundlePath); } public void LoadSceneAsync(string assetBundlePath, Action complete) { loader.LoadSceneAsync(assetBundlePath, complete); } public void UnloadScene(string assetBundlePath) { loader.UnloadScene(assetBundlePath); } public bool ContainsAsset(string assetPath) { return loader.ContainsAsset(assetPath); } public override void Update() { if (loader != null) { loader.Tick(); } } } }