// *********************************************************************** // Assembly : Unity // Author : Kimch // Created : // // Last Modified By : Kimch // Last Modified On : // *********************************************************************** // // // *********************************************************************** //#if UNITY_EDITOR //#define USE_ASSETDATABASE //#endif //#define USE_ASSETBUNDLE //#define USE_RESOURCE #define USE_ADDRESSABLES namespace G { using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using Object = UnityEngine.Object; #region INTERFACE public interface IAsyncR { /// Gets a value indicating whether this is done. bool done { get; } /// Gets the error. string error { get; } /// Gets or sets the progress. float progress { get; } /// Gets or sets the data. object asyncData { get; } /// Gets the asset bundle. AssetBundle assetBundle { get; } } #endregion /// /// /// partial class AssetProxy : F.GameProxy { private const string GLOBAL_ASSET_POOL_NAME = "global"; private const string TEMPORARY_ASSET_POOL_NAME = "temporary"; private const string INSTANCES_POOL_NAME = "instances"; #region Model private class AsyncR : IAsyncR { #region Field /// /// /// private float _progress; /// /// /// private string _error; /// /// /// private object _data; #endregion #region Property bool IAsyncR.done { get { return _progress > 1f; } } string IAsyncR.error { get { return _error; } } float IAsyncR.progress { get { return _progress; } } object IAsyncR.asyncData { get { return _data; } } AssetBundle IAsyncR.assetBundle { get { return _data as AssetBundle; } } #endregion #region Method public void AsyncProcess(float progress) { _progress = progress; _error = null; _data = null; } public void AsyncSuccess(object data) { _progress = 1.0001f; _error = null; _data = data; } public void AsyncFailure(string error) { _progress = 1.0001f; _error = error; _data = null; } #endregion } #endregion #region FIELD /// /// 异步加载回调 /// private AsyncR _asyncR = new AsyncR(); /// /// /// private Dictionary _persistentAssets = new Dictionary(StringComparer.OrdinalIgnoreCase); /// /// /// private Dictionary _temporaryAssets = new Dictionary(StringComparer.OrdinalIgnoreCase); #endregion #region Proxy /// /// /// public override int priority { get { return int.MaxValue; } } /// /// 已经初始化 /// public bool initialized { get; private set; } public override void Init() { #if USE_ADDRESSABLES Addressables.InitializeAsync().Completed += (handle) => { this.initialized = true; KUIBind.Bind(null, this.UIAsyncInstantiater, this.UIReleaser); }; #elif USE_ASSETBUNDLE F.KFramework.ResourceManager.InitResources((errorMsg) => { if (string.IsNullOrEmpty(errorMsg)) { initialized = true; } }); #else this.initialized = true; #endif CreateReleasePool(INSTANCES_POOL_NAME); CreateReleasePool(GLOBAL_ASSET_POOL_NAME); } /// /// /// /// public override Task LoadAsync() { Preload(); return TryGetGlobalAssetsAsync("global").Task; } /// /// /// public override void LoadCompleted() { //Preload(); } private void SceneManager_sceneLoaded(UnityEngine.SceneManagement.Scene arg0, UnityEngine.SceneManagement.LoadSceneMode arg1) { } private void SceneManager_sceneUnloaded(UnityEngine.SceneManagement.Scene arg0) { RemoveReleasePool(TEMPORARY_ASSET_POOL_NAME); CreateReleasePool(TEMPORARY_ASSET_POOL_NAME); System.GC.Collect(); } /// /// 预加载 /// void Preload() { StartCoroutine(PreloadCO()); } /// /// /// /// IEnumerator PreloadCO() { //yield return null; yield return new WaitForSeconds(0.3f); //Debug.Log("Preload " + Time.frameCount); //yield return new WaitForSecondsRealtime(5); var handle = TryGetGlobalAssetsAsync("icon"); yield return handle; IconProxy.Instance.LoadAtlas(handle.Result); //TryGetGlobalAssetAsync("ui_w_main"); } #endregion #region API public void CheckAndUpdateAssets(Callback2 callback) { StartCoroutine(UpdateAsync(callback)); } private IEnumerator UpdateAsync(Callback2 callback) { //手动检查更新 var checkHandle = Addressables.CheckForCatalogUpdates(false); PostNotification(GlobalDefine.EVENT_CHECK_ASSET, (AsyncOperationHandle)checkHandle, "检查资源更新"); yield return checkHandle; if (checkHandle.Result.Count > 0) { Debug.Log("有更新的CataLogs"); //ShowInfo("有更新的CataLog Count : " + checkHandle.Result.Count); var updateHandle = Addressables.UpdateCatalogs(checkHandle.Result, false); PostNotification(GlobalDefine.EVENT_UPDATE_ASSET, (AsyncOperationHandle)updateHandle, "更新资源目录"); yield return updateHandle; var locators = updateHandle.Result; foreach (var locator in locators) { var sizeHandle = Addressables.GetDownloadSizeAsync(locator.Keys); yield return sizeHandle; var downloadSize = sizeHandle.Result; Debug.Log("下载资源大小: " + downloadSize); Addressables.Release(sizeHandle); if (downloadSize > 0) { var downloadHandle = Addressables.DownloadDependenciesAsync(locator.Keys, Addressables.MergeMode.Union); PostNotification(GlobalDefine.EVENT_DOWNLOAD_ASSET, downloadHandle, $"下载{locator.ToString()}"); while (!downloadHandle.IsDone) { yield return null; } Debug.Log($"{locator.ToString()}下载完成"); Addressables.Release(downloadHandle); } } Debug.Log("更新完成"); Addressables.Release(updateHandle); } else { Debug.Log("没有要更新的内容"); } Addressables.Release(checkHandle); callback?.Invoke(0, ""); callback = null; } public void Repair() { Addressables.ClearResourceLocators(); Caching.ClearCache(); } /// /// (手动加载) /// /// /// /// public AsyncOperationHandle GetAssetAsync(string key) { return Addressables.LoadAssetAsync(key); } /// /// (手动加载) /// /// /// /// public AsyncOperationHandle> GetAssetsAsync(string key) { return Addressables.LoadAssetsAsync(key, null); } /// /// (手动释放) /// /// /// public void Release(TObject obj) { Addressables.Release(obj); } /// /// (手动释放) /// /// public void Release(AsyncOperationHandle handle) { Addressables.Release(handle); } /// /// (手动释放) /// /// /// public void Release(AsyncOperationHandle handle) { Addressables.Release(handle); } /// /// /// /// /// public AsyncOperationHandle InstantiateAsync(string name) { string key = name;// "UI/" + name + ".prefab"; var resultT = Addressables.InstantiateAsync(key); return resultT; } /// /// /// /// /// /// public AsyncOperationHandle InstantiateAsync(string name, Transform parent) { string key = name;// "UI/" + name + ".prefab"; var resultT = Addressables.InstantiateAsync(key, parent); return resultT; } /// /// /// /// /// public bool ReleaseInstance(AsyncOperationHandle handle) { return Addressables.ReleaseInstance(handle); } /// /// /// /// /// public bool ReleaseInstance(AsyncOperationHandle handle) { return Addressables.ReleaseInstance(handle); } /// /// /// /// public bool ReleaseInstance(GameObject instance) { return Addressables.ReleaseInstance(instance); } /// /// 使用自动释放池 /// /// /// /// public AsyncOperationHandle TryGetAssetAsync(string key, string pool) { if (TryGetHandleInReleasePool(key, out AsyncOperationHandle result, pool)) { return result.Convert(); } var resultT = Addressables.LoadAssetAsync(key); AddHandleToReleasePool(key, resultT, pool); return resultT; } /// /// 使用自动释放池 /// /// /// /// public AsyncOperationHandle> TryGetAssetsAsync(string key, string pool) { if (TryGetHandleInReleasePool(key, out AsyncOperationHandle result, pool)) { return result.Convert>(); } var resultT = Addressables.LoadAssetsAsync(key, null); AddHandleToReleasePool(key, resultT, pool); return resultT; } /// /// 全局(游戏关闭时释放) /// /// /// /// public AsyncOperationHandle TryGetGlobalAssetAsync(string key) { return TryGetAssetAsync(key, GLOBAL_ASSET_POOL_NAME); } /// /// 全局(游戏关闭时释放) /// /// /// /// public AsyncOperationHandle> TryGetGlobalAssetsAsync(string key) { return TryGetAssetsAsync(key, GLOBAL_ASSET_POOL_NAME); } /// /// 临时(场景切换时释放) /// /// /// /// public AsyncOperationHandle TryGetTemporaryAssetAsync(string key) { return TryGetAssetAsync(key, TEMPORARY_ASSET_POOL_NAME); } /// /// /// /// /// /// public AsyncOperationHandle> TryGetTemporaryAssetsAsync(string key) { return TryGetAssetsAsync(key, TEMPORARY_ASSET_POOL_NAME); } /// /// /// /// /// public AsyncOperationHandle TryInstantiateAsync(string name, Transform parent) { string key = name;// "UI/" + name + ".prefab"; if (TryGetHandleInReleasePool(key, out AsyncOperationHandle result, INSTANCES_POOL_NAME)) { return result.Convert(); } var resultT = Addressables.InstantiateAsync(key, parent); AddHandleToReleasePool(key, resultT, INSTANCES_POOL_NAME); return resultT; } /// /// ui框架 /// /// /// public void UIAsyncInstantiater(string name, Transform parent, Action callback) { string key = name;// "UI/" + name + ".prefab"; if (TryGetHandleInReleasePool(key, out AsyncOperationHandle result, INSTANCES_POOL_NAME)) { var handle = result.Convert(); if (handle.Result) handle.Result.transform.SetParent(parent); callback?.Invoke(handle.Result); return; } var resultT = Addressables.InstantiateAsync(key, parent); resultT.Completed += (handle) => { if (handle.Status == AsyncOperationStatus.Succeeded) { var instance = handle.Result; instance.name = System.IO.Path.GetFileNameWithoutExtension(key); callback?.Invoke(handle.Result); } }; AddHandleToReleasePool(key, resultT, INSTANCES_POOL_NAME); } /// /// ui框架 /// /// public void UIReleaser(Object instance) { RemoveHandleInReleasePool(instance.name, INSTANCES_POOL_NAME); Addressables.ReleaseInstance((GameObject)instance); } #endregion #region UNITY public AssetProxy() { _Instance = this; UnityEngine.SceneManagement.SceneManager.sceneLoaded += this.SceneManager_sceneLoaded; UnityEngine.SceneManagement.SceneManager.sceneUnloaded += this.SceneManager_sceneUnloaded; Application.lowMemory += OnLowMemoryCallback; } #endregion #region STATIC private static AssetProxy _Instance; public static AssetProxy Instance { get { return _Instance; } } #endregion } }