A very useful AssetBundle resource loader

Loxodon Framework Bundle is a very useful AssetBundle loader as well as an AssetBundle redundancy analysis tool.It automatically manages the complex dependencies between AssetBundles and maintains the dependencies between AssetBundles by reference counting.You can either preload an AssetBundle to manage its release or load resources directly through an asynchronous resource loading function, which automatically finds the AB package where the resources are located, automatically loads AB, and automatically releases AB after use.It also supports weak caching and does not need to reopen AB if the object template is already in the cache.It supports multiple loading modes, WWW loading, UnityWebRequest loading, File loading, etc. (In Unity5.6 and above, do not use WWW loader, it will produce peak memory).It provides a packaging interface for AssetBundle that supports encrypting AB packages (only sensitive resources are recommended because performance is affected).It also bypasses some bug s in earlier versions of Unity3D, such as multiple collaborations loading the same resource concurrently, which can cause errors in the android system.Its redundancy analysis is done by unpacking AssetBundle, which is more accurate than the redundancy analyzed in editor mode.

Download address: AssetStore Download

**QQ Group: **622321589

Introduction to Packaging Tools

  • Edit packaged tools:

  • Packed file summary information

  • Packed file

  • Redundancy analysis tools

  • Redundancy Analysis Results

Use examples

  • Initialize IResources

The whole project is Interface-oriented and any component can be customized or optional. The following figure is an example of my default.

        IResources CreateResources()
        {
            IResources resources = null;
#if UNITY_EDITOR
            if (SimulationSetting.IsSimulationMode)
            {
                Debug.Log("Use SimulationResources. Run In Editor");

                /* Create a PathInfoParser. */
                //IPathInfoParser pathInfoParser = new SimplePathInfoParser("@");
                IPathInfoParser pathInfoParser = new SimulationAutoMappingPathInfoParser();

                /* Create a BundleManager */
                IBundleManager manager = new SimulationBundleManager();

                /* Create a BundleResources */
                resources = new SimulationResources(pathInfoParser, manager);
            }
            else
#endif
            {
                /* Create a BundleManifestLoader. */
                IBundleManifestLoader manifestLoader = new BundleManifestLoader();

                /* Loads BundleManifest. */
                BundleManifest manifest = manifestLoader.Load(BundleUtil.GetReadOnlyDirectory() + BundleSetting.ManifestFilename);

                //manifest.ActiveVariants = new string[] { "", "sd" };
                manifest.ActiveVariants = new string[] { "", "hd" };

                /* Create a PathInfoParser. */
                //IPathInfoParser pathInfoParser = new SimplePathInfoParser("@");
                IPathInfoParser pathInfoParser = new AutoMappingPathInfoParser(manifest);

                /* Create a BundleLoaderBuilder */
                //ILoaderBuilder builder = new WWWBundleLoaderBuilder(new Uri(BundleUtil.GetReadOnlyDirectory()), false);

                /* AES128_CBC_PKCS7 */
                RijndaelCryptograph rijndaelCryptograph = new RijndaelCryptograph(128, Encoding.ASCII.GetBytes(this.key), Encoding.ASCII.GetBytes(this.iv));

                /* Use a custom BundleLoaderBuilder */
                ILoaderBuilder builder = new CustomBundleLoaderBuilder(new Uri(BundleUtil.GetReadOnlyDirectory()), false, rijndaelCryptograph);

                /* Create a BundleManager */
                IBundleManager manager = new BundleManager(manifest, builder);

                /* Create a BundleResources */
                resources = new BundleResources(pathInfoParser, manager);
            }
            return resources;
        }
  • Query rules for custom AB

AssetBundle resources can be cached in Unity3D, persisted, or Streaming Assets, where you can customize your loading rules and choose to use what you like about how to store resources and generally how projects update resources.Loader (WWW, UnityWebRequest, File, etc.).

using System;

using Loxodon.Framework.Bundles;

namespace Loxodon.Framework.Examples.Bundle
{
    public class CustomBundleLoaderBuilder : AbstractLoaderBuilder
    {
        private bool useCache;
        private IDecryptor decryptor;

        public CustomBundleLoaderBuilder(Uri baseUri, bool useCache) : this(baseUri, useCache, null)
        {
        }

        public CustomBundleLoaderBuilder(Uri baseUri, bool useCache, IDecryptor decryptor) : base(baseUri)
        {
            this.useCache = useCache;
            this.decryptor = decryptor;
        }

        public override BundleLoader Create(BundleManager manager, BundleInfo bundleInfo, BundleLoader[] dependencies)
        {
            //Customize the rules for finding assets.

            Uri loadBaseUri = this.BaseUri; //eg: http://your ip/bundles

            if (this.useCache && BundleUtil.ExistsInCache(bundleInfo))
            {
                //Load assets from the cache of Unity3d.
                loadBaseUri = this.BaseUri;
#if UNITY_5_4_OR_NEWER
                return new UnityWebRequestBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager, this.useCache);
#else
                return new WWWBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager, this.useCache);
#endif
            }

            if (BundleUtil.ExistsInStorableDirectory(bundleInfo))
            {
                //Load assets from the "Application.persistentDataPath/bundles" folder.
                /* Path: Application.persistentDataPath + "/bundles/" + bundleInfo.Filename  */
                loadBaseUri = new Uri(BundleUtil.GetStorableDirectory());
            }

#if !UNITY_WEBGL || UNITY_EDITOR
            else if (BundleUtil.ExistsInReadOnlyDirectory(bundleInfo))
            {
                //Load assets from the "Application.streamingAssetsPath/bundles" folder.
                /* Path: Application.streamingAssetsPath + "/bundles/" + bundleInfo.Filename */

                loadBaseUri = new Uri(BundleUtil.GetReadOnlyDirectory());
            }
#endif

            if (bundleInfo.IsEncrypted)
            {
                if (this.decryptor != null && bundleInfo.Encoding.Equals(decryptor.AlgorithmName))
                    return new CryptographBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager, decryptor);

                throw new NotSupportedException(string.Format("Not support the encryption algorithm '{0}'.", bundleInfo.Encoding));
            }


            //Loads assets from an Internet address if it does not exist in the local directory.
#if UNITY_5_4_OR_NEWER
            if (this.IsRemoteUri(loadBaseUri))
                return new UnityWebRequestBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager, this.useCache);
            else
                return new FileAsyncBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager);
#else
            return new WWWBundleLoader(new Uri(loadBaseUri, bundleInfo.Filename), bundleInfo, dependencies, manager, this.useCache);
#endif
        }
    }
}
  • Load a resource

Loading resources is based on the path of the resource. If you choose a path resolver that automatically maps paths, then the ASETBUndle package you are in can be found automatically by the path of the resource.Below is an example of resource loading.

  1. Loading a resource through callbacks
        void Load(string[] names)
        {
            IProgressResult<float, GameObject[]> result = resources.LoadAssetsAsync<GameObject>(names);
            result.Callbackable().OnProgressCallback(p =>
            {
                Debug.LogFormat("Progress:{0}%", p * 100);
            });
            result.Callbackable().OnCallback((r) =>
            {
                try
                {
                    if (r.Exception != null)
                        throw r.Exception;

                    foreach (GameObject template in r.Result)
                    {
                        GameObject.Instantiate(template);
                    }

                }
                catch (Exception e)
                {
                    Debug.LogErrorFormat("Load failure.Error:{0}", e);
                }
            });
        }

2. Loading scenes through callbacks

        void LoadSceneByCallback(string sceneName)
        {
            ISceneLoadingResult<Scene> result = this.resources.LoadSceneAsync(sceneName);
            result.AllowSceneActivation = false;

            result.OnProgressCallback(p =>
            {
                //Debug.LogFormat("Loading {0}%", (p * 100));
            });

            result.OnStateChangedCallback(state =>
            {
                if (state == LoadState.Failed)
                    Debug.LogFormat("Loads scene '{0}' failure.Error:{1}", sceneName, result.Exception);
                else if (state == LoadState.Completed)
                    Debug.LogFormat("Loads scene '{0}' completed.", sceneName);
                else if (state == LoadState.AssetBundleLoaded)
                    Debug.LogFormat("The AssetBundle has been loaded.");
                else if (state == LoadState.SceneActivationReady)
                {
                    Debug.LogFormat("Ready to activate the scene.");
                    result.AllowSceneActivation = true;
                }
            });
        }

3. Loading scenarios through a collaboration

        IEnumerator LoadSceneByCoroutine(string sceneName)
        {
            ISceneLoadingResult<Scene> result = this.resources.LoadSceneAsync(sceneName);
            while (!result.IsDone)
            {
                //Debug.LogFormat("Loading {0}%", (result.Progress * 100));
                yield return null;
            }

            if (result.Exception != null)
            {
                Debug.LogFormat("Loads scene '{0}' failure.Error:{1}", sceneName, result.Exception);
            }
            else
            {
                Debug.LogFormat("Loads scene '{0}' completed.", sceneName);
            }
        }
  • Download example

I provide an example of an AssetBundle resource download that uses the latest version of the resource index library, Manifest.dat, to find AB resources that do not exist locally, and then download the missing AB resources locally over the network.

IEnumerator Download()
        {
            this.downloading = true;
            try
            {
                IProgressResult<Progress, BundleManifest> manifestResult = this.downloader.DownloadManifest(BundleSetting.ManifestFilename);

                yield return manifestResult.WaitForDone();

                if (manifestResult.Exception != null)
                {
                    Debug.LogFormat("Downloads BundleManifest failure.Error:{0}", manifestResult.Exception);
                    yield break;
                }

                BundleManifest manifest = manifestResult.Result;

                IProgressResult<float, List<BundleInfo>> bundlesResult = this.downloader.GetDownloadList(manifest);
                yield return bundlesResult.WaitForDone();

                List<BundleInfo> bundles = bundlesResult.Result;

                if (bundles == null || bundles.Count <= 0)
                {
                    Debug.LogFormat("Please clear cache and remove StreamingAssets,try again.");
                    yield break;
                }

                IProgressResult<Progress, bool> downloadResult = this.downloader.DownloadBundles(bundles);
                downloadResult.Callbackable().OnProgressCallback(p =>
                {
                    Debug.LogFormat("Downloading {0:F2}KB/{1:F2}KB {2:F3}KB/S", p.GetCompletedSize(UNIT.KB), p.GetTotalSize(UNIT.KB), p.GetSpeed(UNIT.KB));
                });

                yield return downloadResult.WaitForDone();

                if (downloadResult.Exception != null)
                {
                    Debug.LogFormat("Downloads AssetBundle failure.Error:{0}", downloadResult.Exception);
                    yield break;
                }

                Debug.Log("OK");

                if (this.resources != null)
                {
                    //update BundleManager's manifest
                    BundleManager manager = (this.resources as BundleResources).BundleManager as BundleManager;
                    manager.BundleManifest = manifest;
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.OpenWithDefaultApp(BundleUtil.GetStorableDirectory());
#endif

            }
            finally
            {
                this.downloading = false;
            }
        }

Here is an introduction to this project on AssetStore

AssetBundle Manager for Unity3D

Loxodon Framework Bundle is an AssetBundle manager.It provides a functionality that can automatically manage/load an AssetBundle and its dependencies from local or remote location.Asset Dependency Management including BundleManifest that keep track of every AssetBundle and all of their dependencies. An AssetBundle Simulation Mode which allows for iterative testing of AssetBundles in a the Unity editor without ever building an AssetBundle.

The Loxodon Framework Bundle includes all the source code, it works alone, or works with the Loxodon Framework, AssetBundles-Browser.

For tutorials,examples and support,please see the project.You can also discuss the project in the Unity Forums.

Asset Redundancy Analyzer

The asset redundancy analyzer can help you find the redundant assets included in the AssetsBundles.Create a fingerprint for the asset by collecting the characteristic data of the asset. Find out the redundant assets in all AssetBundles by fingerprint comparison.it only supports the AssetBundle of Unity 5.6 or higher.

Tested in Unity 3D on the following platforms:

PC/Mac/Linux

Android

IOS

UWP(Windows 10)

WebGL

Key features:

  • Support encryption and decoding of the AssetBundle files (supports encryption and decryption of AssetBundle files);
  • Use reference counting to manage the dependencies of AssetBundle (use reference counting to manage dependencies of AssetBundle);
  • Automatically unloading AssetBundle with reference count 0 by destructor "Dispose" method (AssetBundle is automatically unloaded through a destructor or Dispose function when the reference count is 0);
  • Use weak cache to optimize load performance (use weak cache to optimize load performance);
  • Interface-oriented programming, you can customize the loader and file search rules for the AssetBundle (interface-oriented programming, you can customize the loader, you can customize the search rules for the AssetBundle);
  • Support for simulating loading in the editor without building AssetBundles (under the editor, supports loading resources in a way that simulates AssetBundles for easy testing);
  • Supports the unpacking and the redundancy analysis of the AssetBundle (supports resource redundancy analysis through the AssetBundle package, which is more accurate than redundancy analysis in Editor mode);

For More Information Contact Us at: yangpc.china@gmail.com

Keywords: encoding Unity Android ascii

Added by lisa3711 on Fri, 06 Sep 2019 06:36:54 +0300