public static BundleAsyncOperation <AssetbundleBuildManifest> GetManifest() { var result = new BundleAsyncOperation <AssetbundleBuildManifest>(); s_Helper.StartCoroutine(CoGetManifest(result)); return(result); }
/// <summary> /// acutally download assetbundles load from cache if cached /// </summary> /// <param name="manifest">manifest you get from GetManifest() function</param> /// <param name="subsetNames">names that you interested among full bundle list(optional)</param> public static BundleAsyncOperation <bool> DownloadAssetBundles(AssetbundleBuildManifest manifest, IEnumerable <string> subsetNames = null) { var result = new BundleAsyncOperation <bool>(); s_Helper.StartCoroutine(CoDownloadAssetBundles(manifest, subsetNames, result)); return(result); }
public static BundleAsyncOperation Initialize(bool autoReloadBundle = true) { var result = new BundleAsyncOperation(); s_Helper.StartCoroutine(CoInitalizeLocalBundles(result, autoReloadBundle)); return(result); }
/// <summary> /// acutally download assetbundles load from cache if cached /// </summary> /// <param name="hardUnload">hard unload reloaded bundle</param> /// <returns>returns bundle has been reloaded</returns> public static BundleAsyncOperation <bool> DownloadAssetBundles(AssetbundleBuildManifest manifest, bool hardUnload = false) { var result = new BundleAsyncOperation <bool>(); s_Helper.StartCoroutine(CoDownloadAssetBundles(manifest, hardUnload, result)); return(result); }
static IEnumerator CoGetManifest(BundleAsyncOperation <AssetbundleBuildManifest> result) { if (!Initialized) { Debug.LogError("Do Initialize first"); result.Done(BundleErrorCode.NotInitialized); yield break; } #if UNITY_EDITOR if (UseAssetDatabase) { result.Result = new AssetbundleBuildManifest(); result.Done(BundleErrorCode.Success); yield break; } #endif var manifestReq = UnityWebRequest.Get(Utility.CombinePath(RemoteURL, AssetbundleBuildSettings.ManifestFileName).Replace('\\', '/')); yield return(manifestReq.SendWebRequest()); if (result.IsCancelled) { manifestReq.Dispose(); yield break; } if (manifestReq.isHttpError || manifestReq.isNetworkError) { result.Done(BundleErrorCode.NetworkError); yield break; } var remoteManifestJson = manifestReq.downloadHandler.text; manifestReq.Dispose(); if (!AssetbundleBuildManifest.TryParse(remoteManifestJson, out var remoteManifest)) { result.Done(BundleErrorCode.ManifestParseError); yield break; } result.Result = remoteManifest; result.Done(BundleErrorCode.Success); }
static IEnumerator CoDownloadAssetBundles(AssetbundleBuildManifest manifest, IEnumerable <string> subsetNames, BundleAsyncOperation <bool> result) { if (!Initialized) { Debug.LogError("Do Initialize first"); result.Done(BundleErrorCode.NotInitialized); yield break; } #if UNITY_EDITOR if (UseAssetDatabase) { result.Done(BundleErrorCode.Success); yield break; } #endif var bundlesToUnload = new HashSet <string>(s_AssetBundles.Keys); var downloadBundleList = subsetNames == null ? manifest.BundleInfos : manifest.CollectSubsetBundleInfoes(subsetNames); var bundleReplaced = false; //bundle has been replaced result.SetIndexLength(downloadBundleList.Count); for (int i = 0; i < downloadBundleList.Count; i++) { result.SetCurrentIndex(i); var bundleInfo = downloadBundleList[i]; //remove from the set so we can track bundles that should be cleared bundlesToUnload.Remove(bundleInfo.BundleName); var islocalBundle = s_LocalBundles.TryGetValue(bundleInfo.BundleName, out var localHash) && localHash == bundleInfo.Hash; var isCached = Caching.IsVersionCached(bundleInfo.AsCached); result.SetCachedBundle(isCached); var loadURL = islocalBundle ? Utility.CombinePath(LocalURL, bundleInfo.BundleName) : Utility.CombinePath(RemoteURL, bundleInfo.BundleName); if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName}, loadURL {loadURL}, isLocalBundle : {islocalBundle}, isCached {isCached}"); } LoadedBundle previousBundle; if (s_AssetBundles.TryGetValue(bundleInfo.BundleName, out previousBundle) && previousBundle.Hash == bundleInfo.Hash) { if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName} Complete - load skipped"); } } else { var bundleReq = islocalBundle ? UnityWebRequestAssetBundle.GetAssetBundle(loadURL) : UnityWebRequestAssetBundle.GetAssetBundle(loadURL, bundleInfo.AsCached); var operation = bundleReq.SendWebRequest(); while (!bundleReq.isDone) { result.SetProgress(operation.progress); yield return(null); } if (bundleReq.isNetworkError || bundleReq.isHttpError) { result.Done(BundleErrorCode.NetworkError); yield break; } if (s_AssetBundles.TryGetValue(bundleInfo.BundleName, out previousBundle)) { bundleReplaced = true; previousBundle.Bundle.Unload(false); if (previousBundle.RequestForReload != null) { previousBundle.RequestForReload.Dispose(); //dispose reload bundle } s_AssetBundles.Remove(bundleInfo.BundleName); } var loadedBundle = new LoadedBundle(bundleInfo, loadURL, DownloadHandlerAssetBundle.GetContent(bundleReq), islocalBundle); s_AssetBundles.Add(bundleInfo.BundleName, loadedBundle); CollectSceneNames(loadedBundle); if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName} Complete"); } bundleReq.Dispose(); } } //let's drop unknown bundles loaded foreach (var name in bundlesToUnload) { var bundleInfo = s_AssetBundles[name]; bundleInfo.Bundle.Unload(false); if (bundleInfo.RequestForReload != null) { bundleInfo.RequestForReload.Dispose(); //dispose reload bundle } s_AssetBundles.Remove(bundleInfo.Name); } //bump entire bundles' usage timestamp //we use manifest directly to find out entire list for (int i = 0; i < manifest.BundleInfos.Count; i++) { var cachedInfo = manifest.BundleInfos[i].AsCached; if (Caching.IsVersionCached(cachedInfo)) { Caching.MarkAsUsed(cachedInfo); } } if (LogMessages) { Debug.Log($"CacheUsed Before Cleanup : {Caching.defaultCache.spaceOccupied} bytes"); } Caching.ClearCache(600); //as we bumped entire list right before clear, let it be just 600 if (LogMessages) { Debug.Log($"CacheUsed After CleanUp : {Caching.defaultCache.spaceOccupied} bytes"); } PlayerPrefs.SetString("CachedManifest", JsonUtility.ToJson(manifest)); GlobalBundleHash = manifest.GlobalHash.ToString(); result.Result = bundleReplaced; result.Done(BundleErrorCode.Success); }
static IEnumerator CoInitalizeLocalBundles(BundleAsyncOperation result, bool autoReloadBundle) { if (Initialized) { result.Done(BundleErrorCode.Success); yield break; } AutoReloadBundle = autoReloadBundle; if (LogMessages) { Debug.Log($"LocalURL : {LocalURL}"); } foreach (var kv in s_AssetBundles) { kv.Value.Bundle.Unload(false); } s_SceneNames.Clear(); s_AssetBundles.Clear(); s_LocalBundles.Clear(); var manifestReq = UnityWebRequest.Get(Utility.CombinePath(LocalURL, AssetbundleBuildSettings.ManifestFileName)); yield return(manifestReq.SendWebRequest()); if (manifestReq.isHttpError || manifestReq.isNetworkError) { result.Done(BundleErrorCode.NetworkError); yield break; } if (!AssetbundleBuildManifest.TryParse(manifestReq.downloadHandler.text, out var localManifest)) { result.Done(BundleErrorCode.ManifestParseError); yield break; } //cached version is recent one. var cacheIsValid = AssetbundleBuildManifest.TryParse(PlayerPrefs.GetString("CachedManifest", string.Empty), out var cachedManifest) && cachedManifest.BuildTime > localManifest.BuildTime; result.SetIndexLength(localManifest.BundleInfos.Count); for (int i = 0; i < localManifest.BundleInfos.Count; i++) { result.SetCurrentIndex(i); result.SetCachedBundle(true); AssetbundleBuildManifest.BundleInfo bundleInfoToLoad; AssetbundleBuildManifest.BundleInfo cachedBundleInfo = default; var localBundleInfo = localManifest.BundleInfos[i]; bool useLocalBundle = !cacheIsValid || //cache is not valid or... !cachedManifest.TryGetBundleInfo(localBundleInfo.BundleName, out cachedBundleInfo) || //missing bundle or... !Caching.IsVersionCached(cachedBundleInfo.AsCached); //is not cached no unusable. bundleInfoToLoad = useLocalBundle ? localBundleInfo : cachedBundleInfo; var loadPath = Utility.CombinePath(LocalURL, bundleInfoToLoad.BundleName); var bundleReq = UnityWebRequestAssetBundle.GetAssetBundle(loadPath, bundleInfoToLoad.Hash); var bundleOp = bundleReq.SendWebRequest(); while (!bundleOp.isDone) { result.SetProgress(bundleOp.progress); yield return(null); } if (!bundleReq.isHttpError && !bundleReq.isNetworkError) { var loadedBundle = new LoadedBundle(bundleInfoToLoad, loadPath, DownloadHandlerAssetBundle.GetContent(bundleReq), useLocalBundle); s_AssetBundles.Add(localBundleInfo.BundleName, loadedBundle); CollectSceneNames(loadedBundle); if (LogMessages) { Debug.Log($"Local bundle Loaded - Name : {localBundleInfo.BundleName}, Hash : {bundleInfoToLoad.Hash }"); } } else { result.Done(BundleErrorCode.NetworkError); yield break; } bundleReq.Dispose(); s_LocalBundles.Add(localBundleInfo.BundleName, localBundleInfo.Hash); } RemoteURL = Utility.CombinePath(localManifest.RemoteURL, localManifest.BuildTarget); #if UNITY_EDITOR if (s_EditorBuildSettings.EmulateWithoutRemoteURL) { RemoteURL = "file://" + Utility.CombinePath(s_EditorBuildSettings.RemoteOutputPath, UnityEditor.EditorUserBuildSettings.activeBuildTarget.ToString()); } #endif Initialized = true; if (LogMessages) { Debug.Log($"Initialize Success \nRemote URL : {RemoteURL} \nLocal URL : {LocalURL}"); } result.Done(BundleErrorCode.Success); }
static IEnumerator CoDownloadAssetBundles(AssetbundleBuildManifest remoteManifest, bool hardUnload, BundleAsyncOperation <bool> result) { if (!Initialized) { Debug.LogError("Do Initialize first"); result.Done(BundleErrorCode.NotInitialized); yield break; } if (UseAssetDatabase) { result.Done(BundleErrorCode.Success); yield break; } var startTime = Time.realtimeSinceStartup; result.SetIndexLength(remoteManifest.BundleInfos.Count); bool bundleReplaced = false; //bundle has been replaced for (int i = 0; i < remoteManifest.BundleInfos.Count; i++) { result.SetCurrentIndex(i); var bundleInfo = remoteManifest.BundleInfos[i]; var localBundle = s_LocalBundles.TryGetValue(bundleInfo.BundleName, out var localHash) && localHash == bundleInfo.Hash; var isCached = Caching.IsVersionCached(bundleInfo.AsCached); result.SetCachedBundle(isCached); var loadURL = localBundle ? Path.Combine(LocalURL, bundleInfo.BundleName) : Path.Combine(RemoteURL, bundleInfo.BundleName); if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName}, loadURL {loadURL}, isLocalBundle : {localBundle}, isCached {isCached}"); } LoadedBundle previousBundle; if (s_AssetBundles.TryGetValue(bundleInfo.BundleName, out previousBundle) && previousBundle.Hash == bundleInfo.Hash) { if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName} Complete - load skipped"); } } else { var bundleReq = localBundle ? UnityWebRequestAssetBundle.GetAssetBundle(loadURL) : UnityWebRequestAssetBundle.GetAssetBundle(loadURL, bundleInfo.AsCached); var operation = bundleReq.SendWebRequest(); while (!bundleReq.isDone) { result.SetProgress(operation.progress); yield return(null); } if (bundleReq.isNetworkError || bundleReq.isHttpError) { result.Done(BundleErrorCode.NetworkError); yield break; } if (s_AssetBundles.TryGetValue(bundleInfo.BundleName, out previousBundle)) { bundleReplaced = true; previousBundle.Bundle.Unload(hardUnload); if (previousBundle.RequestForReload != null) { previousBundle.RequestForReload.Dispose(); //dispose reload bundle } s_AssetBundles.Remove(bundleInfo.BundleName); } var loadedBundle = new LoadedBundle(bundleInfo, loadURL, DownloadHandlerAssetBundle.GetContent(bundleReq), localBundle); s_AssetBundles.Add(bundleInfo.BundleName, loadedBundle); CollectSceneNames(loadedBundle); if (LogMessages) { Debug.Log($"Loading Bundle Name : {bundleInfo.BundleName} Complete"); } bundleReq.Dispose(); } Caching.MarkAsUsed(bundleInfo.AsCached); } var timeTook = Time.realtimeSinceStartup - startTime; if (LogMessages) { Debug.Log($"CacheUsed Before Cleanup : {Caching.defaultCache.spaceOccupied} bytes"); } Caching.ClearCache((int)timeTook + 600); if (LogMessages) { Debug.Log($"CacheUsed After CleanUp : {Caching.defaultCache.spaceOccupied} bytes"); } PlayerPrefs.SetString("CachedManifest", JsonUtility.ToJson(remoteManifest)); GlobalBundleHash = remoteManifest.GlobalHash.ToString(); result.Result = bundleReplaced; result.Done(BundleErrorCode.Success); }