How to get AssetBundleManifest?

Following the instructions on the official site Unity - Scripting API: Caching I fail to get AssetBundleManifest neither from the server nor from local storage. The end goal is to get AssetBundle’s hash.

Main error message in the console is:

Failed to decompress data for the AssetBundle “Memory”

I tried to use the following:

UnityWebRequest - to load from server

LoadFromFile - to local from local storage

How to do it correctly?

Can you show the code?

After building I receive the main file and the manifest file.

In order to check cache and the updated bundle loading I have to indicate hash of the new Bundle which we can obtain only from AssetBundleManifest(for UnityWebRequest). However I cannot make AssetBundleManifest load properly. I tried to indicate path both to the main file (without extension), and to the manifest file (with .manifest extension)

I try to load AssetBundleManifest using these lines:

AssetBundle manifestBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "dispatcherminigame.manifest"));
AssetBundleManifest manifest = manifestBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

So in order to get AssetBundle’s hash I have to load the file with .manifest extension, right?

Hi,

I am struggling with this too.

Is it a matter of downloading the manifest individually, or is it indeed available within the loading bundle?

Bye,

Jean

1 Like

You load the main asset bundle manifest, then use https://docs.unity3d.com/ScriptReference/AssetBundleManifest.GetAssetBundleHash.html to get the hash

Hi,

thanks for your reply.

the problem is that I can’t find the way to do what you say with code.

I have this:

AssetBundleManifest _m = (AssetBundleManifest)wwwObject.assetBundle.LoadAsset(“AssetBundleManifest”, typeof(AssetBundleManifest));

and that doesn’t work, so I would appreciate a snippet on what to do with the wwwObject.assetBundle once it’s done being downloaded, so far I haven’t found a working snippet from all my searches on google.

AssetBundleManifest _m = (AssetBundleManifest)wwwObject.assetBundle.mainAsset;

that doesn’t work neither.

so if you have a working code snippet to share, I would appreciate it very much.

Bye,

Jean

wwwObject.assetBundle.LoadAsset<AssetBundleManifest>("assetbundlemanifest");

Should work. If not, define what ‘doesn’t work’ means. Do you get an error?

Also, the bundle containing the manifest is the one named after the folder you built to. It also isn’t the file with the .manifest extension, its the bundle file which doesn’t have an extension.

Hi,

That doesn’t work neither, this line returns null, while the assetbundle main asset is well and can be accessed properly.

here’s the url : Dropbox

Maybe you could point me to a url of a testing asset bundle that works? that would be a good way to rule out that the production of this assetbundle is faulty.

and I confirm that the .manifest is not the file I load, but indeed the other one, without extension.

thanks for your patience on this :slight_smile: I hope we’ll get to the bottom of this!

Jean

Hi Jean,

Your bundle returns null on my end too, but I’m using unity 2018.2.2f1 and your manifest is built using 5.6.3f1 by the looks of it (bundles aren’t guaranteed to be compatible with different versions).

What Unity version are you using to build the bundles and project?

Also, post your downloading code. I suppose unitywebrequest isn’t available yet in 5.6.

Here’s an example of a bundle that works for me:

https://s3-eu-west-1.amazonaws.com/byardev.mysmilez.nl/Android

Hi,

yes, it’s built with 5.6, but it should work still right?! I’ll move to 2017 and 2018 to see if I get a different results.

I need to get to the lowest working version as I am providing support for PlayMaker, so it woul dbbe good if I can make it work on 5.6

Bye,

Jean

Out of curiosity I downloaded the unity version the bundles were built in, and I can’t load the manifest either.

What build target was the bundle built for? It has to be the same as the platform you try to load it on.

Post the script used to generate the bundles, and the script that downloads them.

Hi,

I am doing this all in editor for standaloneOsX platform target. does that means it will never work in editor?

Bye,

Jean

No, it should load in the editor.

I just used this build script in the same unity version as you to generate a manifest

using System.IO;
using UnityEditor;

public class CreateAssetBundles
{
    [MenuItem("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles()
    {
        string assetBundleDirectory = "Assets/AssetBundles";
        if(!Directory.Exists(assetBundleDirectory))
        {
            Directory.CreateDirectory(assetBundleDirectory);
        }
       
        BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
    }
}

It outputs this bundle: https://s3-eu-west-1.amazonaws.com/byardev.mysmilez.nl/AssetBundles

And it loads just fine using the previously shared code. The problem has to be in the bundle file itself, try recreating it.

This could even be a problem with dropbox hosting. Perhaps they use some funky compression which messes up the file, try regenerating the bundles and hosting it elsewhere or even in streaming assets.

Hi,

ok, thanks for confirming on your end that works, I’ll debug this Id save it in StreamingAssets already. but as I was loading it from that and was getting null I though it could be something that is only available when you download from the web hence why I tried to put it on the web.

thanks for your help!

Bye,

Jean

I came across this thread as I had the same problem. I think your mistake is that you’re looking in the wrong files. When you create the asset bundles, Unity creates 2 files in your output folder, named after the build target, e.g. WebGL and WebGL.manifest. In order to retrieve the AssetBundleManifest with

wwwObject.assetBundle.LoadAsset<AssetBundleManifest>("assetbundlemanifest");

You need to use the file “WebGL” (without the extension). With that AssetBundleManifest you can get all the info needed about the actual AssetBundles

Hi,

Thanks for your Input!

Bye,

Jean

Jesus. This one took me an entire day to figure out what I did wrong. Thanks for creating the thread since it gave me new ideas on how to get this solved.

However. Here is the code that loads a asset bundle manifest from a given URL:
You don’t have to use the .manifest files!
This solution also handles multiple asset bundles (like different scenes).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class AssetBundleCacheSample : MonoBehaviour
{

    public string manifestPath = "https://www.your-domain.de/AssetBundlesiOS"; // No file extension (this file gets created when you build your bundles)
    public string assetBundlePath = "https://www.your-domain.de/testbundle"; // Also no extension. This is the actual content asset bundle

    private void Start()
    {
        StartCoroutine(DownloadAndCacheAssetBundle());
    }

    IEnumerator DownloadAndCacheAssetBundle()
    {
        // Load the manifest (from url)
        UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(manifestPath);
        yield return www.SendWebRequest();

        AssetBundle manifestBundle = DownloadHandlerAssetBundle.GetContent(www);

        AssetBundleManifest manifest = manifestBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

        // Use the default cache here
        Caching.currentCacheForWriting = Caching.defaultCache;

        string[] allAssetBundleNames = manifest.GetAllAssetBundles();
  
        foreach(string assetBundleName in allAssetBundleNames)
        {
            // Get hash of bundle
            Hash128 hash = manifest.GetAssetBundleHash(assetBundleName);
            Debug.Log("Hash for bundle " + assetBundleName + " is " + hash);
      
            // Download actual content bundle
            UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, hash, 0);
            yield return request.SendWebRequest();

            // This one is crucial for debugging. Code 200 means downloaded from web and Code 0 means loaded from cache.
            Debug.Log(request.responseCode);

            // Download the actual content bundle
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
      
            // List all the cached versions of the given asset bundle
            List<Hash128> listOfCachedVersions = new List<Hash128>();
            Caching.GetCachedVersions(assetBundleName, listOfCachedVersions);

            for (int i = 0; i < listOfCachedVersions.Count; i++)
            {
                Debug.Log("Found cached version of " + assetBundleName + " version: " + listOfCachedVersions[i]);
            }

            // Don't forget to unload the bundle
            bundle.Unload(false);
        }
  
    }

}

Hope someone finds this useful.

Keep it up guys!

Greets

6 Likes

@JannickL : Thank you so much, you save my day! It work like a charm!

@JannickL your solution has one problem: you need to send a request every time you load the bundle. While if you use local manifest file and if you have cached bundle then you can avoid any request to server and speed up loading process.

BTW I am trying to load bundles from server for almost a week. I learned a lot about Unity and Webrequest in general. Currently Addressables has lots of bugs and limitations which cannot be fixed for more than a half year (including high delays on mobile devices) so they are not recommended to be used.

UnityWebRequestAssetBundle also has a problem with showing loading progress… it will be 0 for 98% of the time and then quickly move to 45 and then 100%. There was an answer from Unity developers that this is a feature not a bug =) So if you faced the same problem, try to create your own download handler from DownloadHandlerScript.

i think we all need to read this manual page carefully ,
as it states the following
Loading AssetBundle Manifests
Loading AssetBundle manifests can be incredibly useful. Especially when dealing with AssetBundle dependencies.

To get a useable AssetBundleManifest object, you’ll need to load that additional AssetBundle (the one that’s named the same thing as the folder it’s in) and load an object of type AssetBundleManifest from it.

Loading the manifest itself is done exactly the same as any other Asset from an AssetBundle:

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset(“AssetBundleManifest”);
hope this would help everyone