using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; namespace VRMShaders { public class AssetBundleCache:IDisposable { private Dictionary bundleDict=new Dictionary(); static AssetBundleCache instance; public static AssetBundleCache Instance=>instance??new AssetBundleCache(); private Dictionary>loadingDict=new Dictionary>(); public AssetBundleCache() { instance=this; } /// /// Set Folder Path that material bundle located /// /// public string LoadFolderPath{get;set;} /// /// Toggle to remove bundle hash when loading /// /// public bool IsLocal{get;set;} public void Dispose() { instance=null; foreach(var bundle in bundleDict.Values) { bundle.UnloadAsync(true); } } public async Task GetBundleAssetAsync(string bundleName,string assetName)where T:UnityEngine.Object { AssetBundle bundle=await GetBundleAsync(bundleName); return await bundle.GetAssetAsync(assetName); } public async Task GetBundleAsync(string bundleName) { //Direct load bundle locally by using its name instead of name-hash pair if(IsLocal) bundleName=bundleName.Substring(0, bundleName.LastIndexOf('-')); if(bundleDict.ContainsKey(bundleName)&&bundleDict[bundleName]!=null) { return bundleDict[bundleName]; } else { if(loadingDict.ContainsKey(bundleName)) { return await loadingDict[bundleName]; } var path=Path.Combine(LoadFolderPath,bundleName); #if UNITY_WEBGL var request = UnityWebRequestAssetBundle.GetAssetBundle(path); loadingDict[bundleName]= WaitAssetBundleTask(request,request.SendWebRequest()); #else var quest=AssetBundle.LoadFromFileAsync(path); loadingDict[bundleName]=WaitAssetBundleTask(quest); #endif bundleDict[bundleName]=await loadingDict[bundleName]; return bundleDict[bundleName]; } } private static async Task WaitAssetBundleTask(UnityWebRequest request,UnityWebRequestAsyncOperation operation) { while(!operation.isDone) { await Task.Yield(); } return (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle; } private static async Task WaitAssetBundleTask(AssetBundleCreateRequest request) { while(!request.isDone) { await Task.Yield(); } return request.assetBundle; } } internal static class AssetBundleRequestExtension { internal static async Task GetAssetAsync(this AssetBundle bundle,string assetName) where T:UnityEngine.Object { var quest=bundle.LoadAssetAsync(assetName); await WaitRequestTask(quest); return quest.asset as T; } private static async Task WaitRequestTask(AssetBundleRequest request) { while(!request.isDone) { await Task.Yield(); } } } }