using XGame.Framework.Asyncs; using XGame.Framework.Utils; using UnityEngine; namespace XGame.Framework.Asset { /// /// AssetBundle的加载方式,需要先实现Bundle的Manifest管理 /// internal partial class AssetBundleLoader { /// /// 创建从Repository获取Asset的异步 /// Repository没缓存时则返回Null /// /// /// AssetLoadFromCacheAsync CreateAssetFromCacheAsync(string addressableName) { var source = Repository.PopUnusedAsset(addressableName); if (source != null) { var assetAsync = new AssetLoadFromCacheAsync() { AddressableName = addressableName, Source = source, }; return assetAsync; } return null; } ///// ///// 创建加载Asset的异步 ///// ///// ///// //AssetLoadFromBundleAsync CreateAssetLoadFromBundleAsync(string assetPath) //{ // var assetAsync = AsyncPool.GetAssetAsync(assetPath) as AssetLoadFromBundleAsync; // if (assetAsync == null) // { // assetAsync = new AssetLoadFromBundleAsync // { // Path = assetPath // }; // //记录当前加载的AssetPath // LoadingAssets.Add(assetPath); // assetAsync.On(OnAssetCompleted); // } // return assetAsync; //} /// /// 创建加载Bundle的异步 /// /// /// IAssetAsync CreateBundleAsync(string bundleName) { //var path = FileUtil.GetAssetBundlePath(bundleName); if (Repository.ContainsBundle(bundleName)) return null; var assetAsync = AsyncPool.GetAssetAsync(bundleName); if (assetAsync != null) return assetAsync; #if UNITY_EDITOR || !(UNITY_WEBGL || UNITY_WEIXINMINIGAME) var requestAsync = new AssetBundleCreateRequestAsync { Path = FileUtils.GetAssetBundlePath(bundleName), AddressableName = bundleName, Offset = GetBundleOffest(bundleName) }; #else var requestAsync = new WebRequestAssetBundleAsync { Path = FileUtils.GetAssetBundlePath(bundleName), AddressableName = bundleName, Offset = GetBundleOffest(bundleName) }; #endif requestAsync.On(OnBundleCompleted); //AsyncPool.AddAsync(requestAsync); return requestAsync; } /// /// AssetBundleCreateRequestAsync的回调监听 /// /// void OnBundleCompleted(IAsync async) { if (async is IAssetAsync assetAsync) { var bundleName = assetAsync.AddressableName; var result = assetAsync.GetResult(); var bundleAsset = Repository.GetBundle(bundleName); if (bundleAsset != null) { //bundleAsset.Retain(); AssetsLog.Warn("Bundle load repeated. Name:{0} Last:{1} Next:{2}", bundleName, bundleAsset.Source.GetLongHashCode(), result?.GetLongHashCode()); return; } bundleAsset = AssetCreator.Create(bundleName, result) as BundleAsset; if (bundleAsset != null) { Repository.AddBundle(bundleAsset); } else { AssetsLog.Error("Load bundle failed. Bundle:{0}", bundleName); } } } /// /// AssetLoadFromBundleAsync的回调监听 /// /// void OnAssetCompleted(IAsync async) { if (async is AssetLoadFromBundleAsync assetAsync) { int assetHash = assetAsync.AssetHash; var assetName = assetAsync.AddressableName; //删除当前加载的AssetPath //LoadingAssets.Remove(assetPath); if (assetHash == 0) { AssetsLog.Error($"AssetBundle load failed. Asset is null. Name:{assetName}"); return; } //记录hash if (!Repository.RegistAssetHash(assetHash, assetName)) { //发现重复的Hash记录,不需要再重复记录Bundle的引用计数 //出现重复的原因是异步加载Asset后又使用同步加载了同一个Asset return; } if (TryGetBundleInfo(assetName, out string bundleName, out string[] dependencies)) { //增加依赖bundle的引用计数 //string bundlePath = FileUtil.GetAssetBundlePath(bundleName); Repository.RetainBundle(bundleName); if (dependencies != null) { foreach (var dep in dependencies) { //var depBundlePath = FileUtil.GetAssetBundlePath(dep); Repository.RetainBundle(dep); } } } } } /// /// 异步加载scene的回调 /// /// void OnSceneComplete(IAsync async) { if (async is SceneLoadAsync sceneAsync) { var assetName = sceneAsync.AddressableName; if (TryGetBundleInfo(assetName, out string bundleName, out string[] dependencies)) { //sceneBundle在这里添加到Reponsitory var sceneBundle = Repository.GetBundle(bundleName); if (sceneBundle != null) { AssetsLog.Warn("Bundle load repeated. Name:{0} Last:{1}", bundleName, sceneBundle.Source.GetLongHashCode()); return; } //更新引用计数 Repository.RetainBundle(bundleName); if (dependencies != null) { foreach (var dep in dependencies) { Repository.RetainBundle(dep); } } } } } AssetBundle GetAssetBundleByName(string bundleName) { var bundleAsset = Repository.GetBundle(bundleName); return bundleAsset?.Source as AssetBundle; } } }