Giter Site home page Giter Site logo

assetbundlemanager's Introduction

Asset Bundle Manager (ABM)

Yet another asset bundle manager for Unity.

Why

We felt the AssetBundleManager provided by Unity was complicated and out-dated... So like typical programmers we decided to write our own! We wanted something with few frills and easier to trace & maintain.

Requirements

  • Unity 2017.1 or greater.

Recommendations

This module pairs well with Unity's Asset Bundle Browser (ABB) tool.

How

Initializing

First you need to build your bundles. By default the ABB puts bundles in PROJECT\AssetBundles\PLATFORM and ABM can take advantage of it.

Once the bundles are built you can start accessing them with the manager.

When you are done testing your bundles you need to upload them to a server. They can go anywhere in the server as long as they are contained in a PLATFORM folder. For example, builds for iOS bundles should be accessable from http://www.example.com/AssetBundles/iOS. The full list of supported targets can be found in AssetBundleUtility.cs.

var abm = new AssetBundleManager()

if (Application.isEditor)
    abm.UseSimulatedUri();
else
    abm.SetBaseUri("https://www.example.com/bundles");

abm.Initialize(OnAssetBundleManagerInitialized);

UseSimulatedUri() configures ABM to use ABB's default folder structure to retrieve bundles. This convenience means you don't have to upload your bundles to a remote server in order to test them, you can use your local files instead.

The SetBaseUri(...) function configures ABM to point to a remote server that contains your bundles.

Calling Initialize(...) causes ABM to download the manifest file for your bundles. Once this file is downloaded and processed you are ready to begin downloading bundles.

If you prefer to use a coroutine instead of a callback for initializing:

var abm = new AssetBundleManager();
// ...
var initializeAsync = abm.InitializeAsyn();
yield return initializeAsync;
if (initializeAsync.Success) {
    // ...
}

Both initialize calls will return a boolean to indicate whether the manifest was downloaded successfully or not.

Downloading

Just like initializing you can use either callbacks or coroutines to download bundles.

Callback

public function GetMyBundle() 
{
    abm.GetBundle("MyBundle", OnBundleDownloaded);
}

public function OnBundleDownloaded(AssetBundle bundle)
{
    if (bundle != null) {
        // Do something with the bundle
        abm.UnloadBundle(bundle);
    }
}

Coroutine

/// Coroutine
var bundle = abm.GetBundleAsync(MyBundle);
yield return bundle;

if (bundle.AssetBundle != null) {
    // Do something with bundle.AssetBundle
    abm.UnloadBundle(bundle);
}

If ABM is unable to download the bundle it will log an error describing the problem and return a null bundle. Therefore it's important to check whether the bundle is null before attempting to use it.

By default bundles are cached using Unity's caching system. The exception to this is the manifest file, which is never cached and always downloaded fresh on initialization. You can override this behaviour on non-manifest bundles by including the DownloadSettings parameter on a GetBundle call:

var bundle = abm.GetBundle("MyBundle", OnBundleDownloaded, DownloadSettings.DoNotUseCache);

Notice that the above examples call UnloadBundle(...) after they are done using the bundle. This is to help ABM manage memory and bundle usage. If two scripts download the same bundle then that bundle is reused for both scripts and will remain in memory until BOTH of those scripts unload the bundle. If memory usage is important to you then you must ensure that every script that loads a bundle also unloads the bundle. If you want to keep the bundle in memory and available at any time then feel free to skip the UnloadBundle(...) call.

StreamingAssets

ABM supports pre-caching your bundles with the use of the StreamingAssets folder in Unity. Once your bundles are built you can copy the manifest and any number of bundles to the StreamingAsests\PLATFORM folder in your project. For example if you wanted to pre-cache the SomeBundle iOS bundles you would have a structure like:

PROJECT
  \Assets
    \StreamingAssets
      \iOS
        \iOS
        \iOS.manifest
        \SomeBundle
        \SomeBundle.manifest

When you make a GetBundle(...) call ABM will check to see if that bundle exists in the StreamingAssets folder first and use it if its hash matches the hash of the remote server. If the file does not exist OR the hash is different then the remote bundle is used. You can change this behaviour when initializing ABM by changing the prioritization strategy:

abm.SetPrioritizationStrategy(PrioritizationStrategy.PrioritizeStreamingAssets);

This will tell ABM to always use the StreamingAssets bundle if it exists. If the bundle doesn't exist in StreamingAssets the remote one will be used.

Cleanup

There are two patterns you should follow when using ABM. The first, as mentioned before, is to always unload the bundle when you are finished with it:

abm.UnloadBundle(bundle);

If no other scripts are using this bundle it will be unloaded from memory. Likewise, when you are completely done with ABM (maybe because you're switching scenes and don't need the bundles anymore) you can dispose of it:

abm.Dispose();

This will force ALL bundles (and their objects) to be unloaded.

assetbundlemanager's People

Contributors

danoli3 avatar foddermk avatar giawa avatar rdeluxe avatar sadpandastudios avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

assetbundlemanager's Issues

Lose internet connection

Hi when I am in the middle of an asset download and i lose the internet connection, how can i continue or restart the asset download.

Currently it never triggers the OnBundleDownloaded or maybe i am doing it wrong. Can you help me with this.
Thanks

Cannot connect to destination host error

I'm trying load my datas but giving error. Error downloading [/Users/*/Desktop/Unity Projects//AssetBundles/Android/Android]: [Cannot connect to destination host] there are two android folder but I have one android folder. I did not understand what's going on

Problem for download bundles with dependencies

Добрый день. Я столкнулся с проблема при использовании менеджера. Скачивая пакеты с зависимостями в итоге скачиваются только те пакеты у которых не было зависимостей, а те пакеты у которых была хотя бы одна зависимость не скачиваются. Возможно вы сможете подсказать в чем проблема.

Good afternoon. I encountered a problem when using the manager. Downloading packets with dependencies eventually download only those packages that did not have dependencies, and those packets that have not been downloaded at least one dependence. Perhaps you can suggest a problem.

how to config ABM for this situation?

Hi,
I wanna first thank you for this project, it's indeed easier to use than Unity's abm, and I use it in my project. I had some question about how to config the ABM for this scenario.
our project use asset bundle browser to build asset bundles.
Q:

  1. After build the asset bundles, we put all abs in to a asset server and put some of the abs into streaming asset folder which can be load and played offline,
    how can I configure the ABM to enable it can check the asset bundle cache version, if it's cache, it just load from streamingasset folder, if the cache version is old , it will download from server.

I try this code
abm = new AssetBundleManager(); abm.SetPrioritizationStrategy(AssetBundleManager.PrioritizationStrategy.PrioritizeStreamingAssets); abm.SetBaseUri(GameConfig.GetBaseURI());

I'm not sure it's going to work,

  1. Asset bundle browser build generate the manifest for every asset, in our project, most asset has no dependency, It there any interface that can skip check the manifest dependency globally or for a specific asset bundle ?

3.If I put the IOS, and IOS meanfest bundle in streammingAsset folder, when game start up, It should always to load the IOS ab from asset server, How can I make sure it work in this way when the network is connectable.?

  1. when I use abm.UseStreamingAssetsFolder(), and the IOS path is correct, it always show host is not connectable ? how can i fix this ?

sorry for ask so many questions in a time.

thanks

await GetBundle("nonexistent bundle") never completes the Task

Hello,
Thanks for your great lib, it helps us a lot on our project. :)

I may have found a little issue and wanted to share:

If I await GetBundle for a nonexistent bundle, the Task is never completed and the awaits get stucks.
(Found this in a unit test)/

The code to reproduce is just:

AssetBundle bundle = await assetBundleManager.GetBundle("thisbundledoesntexists");

Diving into your code, I think the issue is in AssetBundleDownloader#Download

Replacing

if (isHttpError) {
                Debug.LogError(string.Format("Error downloading [{0}]: [{1}] [{2}]", uri, req.responseCode, req.error));

                if (retryCount < MAX_RETRY_COUNT && RETRY_ON_ERRORS.Contains(req.responseCode)) {
                    Debug.LogWarning(string.Format("Retrying [{0}] in [{1}] seconds...", uri, RETRY_WAIT_PERIOD));
                    req.Dispose();
                    activeDownloads--;
                    yield return new WaitForSeconds(RETRY_WAIT_PERIOD);
                    InternalHandle(Download(cmd, retryCount + 1));
                    yield break;
                }
            }

            AssetBundle bundle;

            if (isNetworkError) {
                Debug.LogError(string.Format("Error downloading [{0}]: [{1}]", uri, req.error));
                bundle = null;
            } else {
                bundle = DownloadHandlerAssetBundle.GetContent(req);
            }

By

  AssetBundle bundle = null;
            
            if (isHttpError) {
                Debug.LogError(string.Format("Error downloading [{0}]: [{1}] [{2}]", uri, req.responseCode, req.error));

                if (retryCount < MAX_RETRY_COUNT && RETRY_ON_ERRORS.Contains(req.responseCode)) {
                    Debug.LogWarning(string.Format("Retrying [{0}] in [{1}] seconds...", uri, RETRY_WAIT_PERIOD));
                    req.Dispose();
                    activeDownloads--;
                    yield return new WaitForSeconds(RETRY_WAIT_PERIOD);
                    InternalHandle(Download(cmd, retryCount + 1));
                    yield break;
                }
            }
            else
            {
                if (isNetworkError)
                {
                    Debug.LogError(string.Format("Error downloading [{0}]: [{1}]", uri, req.error));
                    bundle = null;
                }
                else
                {
                    bundle = DownloadHandlerAssetBundle.GetContent(req);
                }
            }

was enough to make sure the task is always complete even if the bundle is null. Otherwise, we have an http error but not a network error and it calls DownloadHandlerAssetBundle.GetContent and fails silently.

Cheers!

Cached bundle

Hi, thank you for sharing your ABM
but there's a lot question i want to ask.

How to check if the bundle is already in cache?
and i'm a bit confused about how you compare the version? your code is using caching.IsVersionCached but how i get the Hash128 form AssetBundleDownloadCommand?

I want to make a list of downloadable content (with notification if the downloaded version is updated)

Every script need to write a AssetBundle manager ?

When download bundle from different script , does very script have to has it own abm, and initialize ,then download bundle from server or cache, can you provide an ABM singleton can initialize once and directly load bundle ?

[Request] Download queue and clear specific bundle

I tried to expose the download queue size to make download progress looks like:

current / total files to download
download progress %

but, i can't figure it out how to expose on the ABM class.
also, do manifest contain information for total file size (with dependency)?

Finally deleting specific assetbundle, it can be done with
Caching.ClearCachedVersion(assetbundleName, Hash128)
how to get the downloaded bundle's hash128?
or, is there another way to delete specific downloaded bundle?
Could you give me the explanation?
Thanks

Download progress

I am looking to get the download progress so I can show a progress bar (More than one bundle may be downloaded) to the user. Any tips where should I dig into to achieve this?

Uploading asset bundles on server

Hi, I have a question:

When uploading the asset bundle on server does it need to have all files that were generated or having just the .unity3d is enough?

I am planning of downloading the asset bundles into persistent path and load them from there, does that mean I have to tweak anything in your code?

Using StreamingAssets Folder Fails

Hi,
I am trying to use asset bundles from StreamingAssets folder on Android.
Screen Shot 2020-07-27 at 16 48 16
Screen Shot 2020-07-27 at 16 47 59

You can see above how I built and the resulting files.

When I start the app and investigate logcat, it says :
Error Unity Unable to open archive file: jar:file:///data/app/com.a.b-1/base.apk!/assets/Android/Android

Warn Unity Unable to retrieve manifest file [jar:file:///data/app/com.a.b-1/base.apk!/assets/Android/Android] from StreamingAssets, disabling StreamingAssetsBundleDownloadDecorator.
...

And also I see that when I extract the apk:
Screen Shot 2020-07-27 at 17 14 08

Is there a problem with my file hierarchy?

PS: Thanks for the awesome library!

StandaloneWindows bundle name

Hi,

We are still using this asset, thanks again!

We are building and uploading our ABs using Unity Cloud (in the Post Process step).
It seems that if we build the ABs with "Windows 64" as the build target the output folder is named StandaloneWindows64, same for the manifest.

private static void BuildAssetBundles() {
  var buildPath = GetAssetBundleFolder();

  if (Directory.Exists(buildPath)) {
    Directory.Delete(buildPath, true);
  }

  Directory.CreateDirectory(buildPath);

  // Build asset bundles for the current platform
  BuildPipeline.BuildAssetBundles(buildPath, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
}

private static string GetAssetBundleFolder() {
  return "Assets/StreamingAssets" + "/" + EditorUserBuildSettings.activeBuildTarget;
}

But ofc in AssetBundleUtility.GetPlatformForAssetBundles the bundle name is always set to StandaloneWindows and not StandaloneWindows64.

Not quite sure what to make of that, the best solution would probably be to rename the output folder and manifest during Cloud Build for the windows 64bit target.

Or we could check if windows is 64bits at runtime using this method and select the appropriate bundle name.

Unable to make it work?!?!

Hi,

There must be something im doing wrong.

Im building asset bundle with ABB, when I build the only thing I change is build target: Windows Standalone 64. I don't set the asset bundle name manually from (bottom right) so the ABB makes default name which is the same as the .obj name that i am using for testing.

The output path, i am not touching it and leave the default but the debug is giving me a different path somehow?? It out puts it in project root folder and not in Asset/... which is fine I don't care where the folder is, I tried in asset/AssetBundles as well and it still does not work.

see below image of my console:

assetbundle

this is the code taken from example except that i am only using the simulatedUri

` private AssetBundleManager abm;

// Use this for initialization
private void Start ()
{
    abm = new AssetBundleManager();

    if (Application.isEditor)
        abm.UseSimulatedUri();
   
    abm.Initialize(OnAssetBundleManagerInitialized);	
}

private void OnAssetBundleManagerInitialized(bool success)
{
    if (success)
    {
        abm.GetBundle("plot_02", OnAssetBundleDownloaded);
    }
    else
    {
        Debug.LogError("Error initializing ABM.");
    }
}

private void OnAssetBundleDownloaded(AssetBundle bundle)
{
    if (bundle != null)
    {
        // Do something with the bundle
        abm.UnloadBundle(bundle);
    }

    abm.Dispose();
}`

Any help would be greatly appreciated

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.