Search Unity

How to get AssetBundleManifest?

Discussion in 'Scripting' started by ViktorAcadem, Sep 15, 2017.

  1. ViktorAcadem

    ViktorAcadem

    Joined:
    Jun 30, 2016
    Posts:
    11
    Following the instructions on the official site https://docs.unity3d.com/ScriptReference/Caching.html 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?
     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Can you show the code?
     
  3. ViktorAcadem

    ViktorAcadem

    Joined:
    Jun 30, 2016
    Posts:
    11
    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:
    Code (CSharp):
    1.  
    2. AssetBundle manifestBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "dispatcherminigame.manifest"));
    3. AssetBundleManifest manifest = manifestBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    So in order to get AssetBundle’s hash I have to load the file with .manifest extension, right?
     
  4. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    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
     
    MaryamKamel likes this.
  5. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
  6. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    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
     
  7. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    Code (CSharp):
    1. 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.
     
    Last edited: Aug 23, 2018
  8. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    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 : https://www.dropbox.com/s/bmunwj8c3ohtfoi/bundletest?dl=1

    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 :) I hope we'll get to the bottom of this!

    Jean
     
  9. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    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
     
  10. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    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
     
  11. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    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.
     
  12. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    Hi,

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

    Bye,

    Jean
     
  13. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    No, it should load in the editor.

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

    Code (CSharp):
    1. using System.IO;
    2. using UnityEditor;
    3.  
    4. public class CreateAssetBundles
    5. {
    6.     [MenuItem("Assets/Build AssetBundles")]
    7.     static void BuildAllAssetBundles()
    8.     {
    9.         string assetBundleDirectory = "Assets/AssetBundles";
    10.         if(!Directory.Exists(assetBundleDirectory))
    11.         {
    12.             Directory.CreateDirectory(assetBundleDirectory);
    13.         }
    14.        
    15.         BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
    16.     }
    17. }
    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.
     
  14. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    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
     
  15. Nith666

    Nith666

    Joined:
    Aug 1, 2012
    Posts:
    57
    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
    Code (CSharp):
    1. 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
     
  16. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
    Hi,

    Thanks for your Input!

    Bye,

    Jean
     
  17. JannickL

    JannickL

    Joined:
    May 18, 2016
    Posts:
    78
    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).

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Networking;
    5.  
    6. public class AssetBundleCacheSample : MonoBehaviour
    7. {
    8.  
    9.     public string manifestPath = "https://www.your-domain.de/AssetBundlesiOS"; // No file extension (this file gets created when you build your bundles)
    10.     public string assetBundlePath = "https://www.your-domain.de/testbundle"; // Also no extension. This is the actual content asset bundle
    11.  
    12.     private void Start()
    13.     {
    14.         StartCoroutine(DownloadAndCacheAssetBundle());
    15.     }
    16.  
    17.     IEnumerator DownloadAndCacheAssetBundle()
    18.     {
    19.         // Load the manifest (from url)
    20.         UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(manifestPath);
    21.         yield return www.SendWebRequest();
    22.  
    23.         AssetBundle manifestBundle = DownloadHandlerAssetBundle.GetContent(www);
    24.  
    25.         AssetBundleManifest manifest = manifestBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    26.  
    27.         // Use the default cache here
    28.         Caching.currentCacheForWriting = Caching.defaultCache;
    29.  
    30.         string[] allAssetBundleNames = manifest.GetAllAssetBundles();
    31.  
    32.         foreach(string assetBundleName in allAssetBundleNames)
    33.         {
    34.             // Get hash of bundle
    35.             Hash128 hash = manifest.GetAssetBundleHash(assetBundleName);
    36.             Debug.Log("Hash for bundle " + assetBundleName + " is " + hash);
    37.      
    38.             // Download actual content bundle
    39.             UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, hash, 0);
    40.             yield return request.SendWebRequest();
    41.  
    42.             // This one is crucial for debugging. Code 200 means downloaded from web and Code 0 means loaded from cache.
    43.             Debug.Log(request.responseCode);
    44.  
    45.             // Download the actual content bundle
    46.             AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
    47.      
    48.             // List all the cached versions of the given asset bundle
    49.             List<Hash128> listOfCachedVersions = new List<Hash128>();
    50.             Caching.GetCachedVersions(assetBundleName, listOfCachedVersions);
    51.  
    52.             for (int i = 0; i < listOfCachedVersions.Count; i++)
    53.             {
    54.                 Debug.Log("Found cached version of " + assetBundleName + " version: " + listOfCachedVersions[i]);
    55.             }
    56.  
    57.             // Don't forget to unload the bundle
    58.             bundle.Unload(false);
    59.         }
    60.  
    61.     }
    62.  
    63. }
    64.  
    Hope someone finds this useful.

    Keep it up guys!

    Greets
     
  18. Jumeuan

    Jumeuan

    Joined:
    Mar 14, 2017
    Posts:
    39
    @JannickL : Thank you so much, you save my day! It work like a charm!
     
  19. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    @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.
     
    Last edited: Mar 6, 2020
  20. MaryamKamel

    MaryamKamel

    Joined:
    Feb 5, 2016
    Posts:
    22
    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>("AssetBundleManifest");
    hope this would help everyone
     
  21. skjagan

    skjagan

    Joined:
    May 18, 2020
    Posts:
    6
    In:
    AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    the "("AssetBundleManifest")" should be same or the string name should be changed as my asset bundle is named bundle and its manifest as bundle.manifest?
     
  22. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    You should not replace "AssetBundleManifest". You should provide file name in this line AssetBundle.LoadFromFile(YOU_FILE_PATH) in my case it was AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "Android" + majorVersion)); I am using the code for more than a half year and no issues found.
     
  23. MaryamKamel

    MaryamKamel

    Joined:
    Feb 5, 2016
    Posts:
    22
    @skjagan should be the same this is just the record that holds all the asset bundles data generated for the platform at which you will find each asset bundle name along with its hash code and crc,
    i am really thinking about writing a full tutorial about it as its very ambiguous :confused:
     
  24. IARI

    IARI

    Joined:
    May 8, 2014
    Posts:
    70
    So what are the.manifest files - which are created for each Assetbundle - for anyways?

    When we try to load them, we get
    Failed to decompress data for the AssetBundle 'Memory'.
    (Just like OP)

    JannickL Says, you don't have to use them whatsoever. - but his code still loads a manifest, so i suppose that is "the one that’s named the same thing as the folder it’s in" - as in the the manual.

    andrew_pearce rightfully critizised, that this main-manifest file isn't cached in Jannicks code whatsover.

    MaryamKamel cited the manual passage i mentioned above above - but this also just seems to refer to the overall manifest file.

    But that still leaves me with (and maybe OP + skjagan) with the Question:
    What are the .manifest files for each single bundle used for?


    My current suspicion is: They're good for ... NOTHING.
    Is seems this has just been omitted from the updated documentation.
    While https://docs.unity3d.com/Manual/AssetBundles-Building.html goes into detail about what is created during the build process, and what these small manifest files contains, its complete silent about what they are supposed to be used for. Instead it references:
    https://docs.unity3d.com/Manual/AssetBundles-Native.html
    to learn more about the manifest - but thats only for the Manifest Bundle again.


    The older 5.3 Unity doc says about them:
    • This manifest file is only used for incremental build, not necessary for runtime.
    https://docs.unity3d.com/530/Documentation/Manual/BuildingAssetBundles.html


    thanks Unity ... for a wasted day of work ^^
     
    Last edited: Oct 25, 2020
  25. IARI

    IARI

    Joined:
    May 8, 2014
    Posts:
    70
    And additionally the DownloadHandlerAssetBundle class prohibits accessing the HTTP response from a webrequest as plain text.
    So in case the server responds with something else than status 200 there is NO WAY to read/show the error message from the server.
    Who designs API's like this....

    AGAIN Thank you unity for nothing.
     
    Last edited: Nov 18, 2020
  26. paulo_renan

    paulo_renan

    Joined:
    Jan 4, 2020
    Posts:
    2
    Well, there was a bit of anger on this thread, but it eventually didn't help me much. So after a couple days working on it, here's how I solved it on my end. Hope this helps.

    Put this code on your asset bundle downloader script, call StartCoroutine(Init()) and be happy.

    Code (CSharp):
    1. string assetName = "https://my.server.com/unity/assetBundles/StandaloneWindows/myAssetBundle";
    2. Hash128 assetHash;
    3. AssetBundle _myLoadedAssetBundle;
    4.  
    5. public IEnumerator Init()
    6. {
    7.     while (!Caching.ready)
    8.         yield return null;
    9.  
    10.     if (_flushCache)
    11.     {
    12.         //Debug.Log("Cleared Cache");
    13.         Caching.ClearAllCachedVersions(assetName);
    14.     }
    15.  
    16.     string manifestPath = assetName + ".manifest";
    17.     string assetHashFromManifest;
    18.  
    19.     using (UnityWebRequest request = UnityWebRequest.Get(manifestPath))
    20.     {
    21.         yield return request.SendWebRequest();
    22.         bool debugged = false;
    23.         while (!request.isDone)
    24.         {
    25.             if (request.downloadProgress < 0 && !debugged)
    26.             {
    27.                 debugged = true;
    28.                 Debug.Log("Progress: " + request.downloadProgress + ". Something may have gone wrong when downloading the asset bundle");
    29.             }
    30.  
    31.             if (request.isNetworkError || request.isHttpError)
    32.             {
    33.                 // handle connection timeout or loss while downloading
    34.                 Debug.Log("Connection error: " + request.error);
    35.             }
    36.  
    37.             yield return null;
    38.         }
    39.         Debug.Log(request.downloadHandler.text);
    40.  
    41.         assetHashFromManifest = request.downloadHandler.text.GetManifestHash();
    42.     }
    43.  
    44.     // to properly check if the asset is cached, we first need to download it
    45.     // this defeats the point when it's stored on our server. we only want to download if it's not yet cached
    46.     // so instead, I made a tool to get and parse the asset hash from the manifest file in runtime from the server
    47.     // GetAssetBundle without any Hash nor CRC will download the asset. When used with an assetHash or CRC, it will load from cache
    48.     using (UnityWebRequest request =
    49.         FoundCache(assetHashFromManifest) ?
    50.             UnityWebRequestAssetBundle.GetAssetBundle(assetName, assetHash)
    51.             :
    52.             UnityWebRequestAssetBundle.GetAssetBundle(assetName)
    53.         )
    54.     {
    55.         yield return request.SendWebRequest();
    56.         bool debugged = false;
    57.         while (!request.isDone)
    58.         {
    59.             if (request.downloadProgress < 0 && !debugged)
    60.             {
    61.                 debugged = true;
    62.                 Debug.Log("progress: " + request.downloadProgress);
    63.             }
    64.  
    65.             if (request.isNetworkError || request.isHttpError)
    66.             {
    67.                 // handle connection timeout or loss while downloading
    68.                 Debug.Log("error: " + request.error);
    69.             }
    70.  
    71.             yield return null;
    72.         }
    73.         _myLoadedAssetBundle = DownloadHandlerAssetBundle.GetContent(request);
    74.     }
    75.  
    76.  
    77.     if (!_myLoadedAssetBundle)
    78.         Debug.LogError("No content downloaded.");
    79.  
    80.     yield return LoadAssetBundle();
    81.  
    82.     //Debug.Log("Hash: " + _myLoadedAssetBundle.GetHashCode()); //that doesn't match the hash from the manifest for checking cache
    83.  
    84.     yield return null;
    85. }
    86.  
    87. public bool FoundCache(string assetHashStr)
    88. {
    89.     assetHash = Hash128.Parse(assetHashStr);
    90.     if (Caching.IsVersionCached(assetName, assetHash))
    91.     {
    92.         Debug.Log("Found Cache. Parsed Hash: " + assetHash.ToString());
    93.         return true;
    94.     }
    95.     assetHash = Hash128.Compute(assetHashStr);
    96.     if (Caching.IsVersionCached(assetName, assetHash))
    97.     {
    98.         Debug.Log("Found Cache. Computed Hash: " + assetHash.ToString());
    99.         return true;
    100.     }
    101.     return false;
    102. }
    And that's just a simple extension class I made to offload some of the generic logic
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. public static class MyStringExtensions
    7. {
    8.     public static string GetManifestHash(this string manifestRawText)
    9.     {
    10.         return GetManifestValue(manifestRawText, "Hash:");
    11.     }
    12.     public static string GetManifestCRC(this string manifestRawText)
    13.     {
    14.         return GetManifestValue(manifestRawText, "CRC:");
    15.     }
    16.     public static string GetManifestValue(this string manifestRawText, string lookFor = "Hash:")
    17.     {
    18.         // We don't really need to chop the string, but if we did, that's how I'd do it.
    19.         //string choppedManifest = manifestRawText.Substring(manifestRawText.IndexOf("AssetFileHash:"));
    20.         //choppedManifest = choppedManifest.Remove(choppedManifest.IndexOf("TypeTreeHash:"));
    21.  
    22.         var hashes = manifestRawText
    23.             // separate the text into lines, in an list/array of strings
    24.             .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
    25.             // select only the lines that starts with 'lookFor', ignoring white spaces
    26.             .Where(x => x.Trim().StartsWith(lookFor))
    27.             // convert result to array
    28.             .ToArray();
    29.         string myParsedHash = hashes
    30.             // on the manifest file, the hash we need is always the first (AssetFileHash), so here we just take the first one found.
    31.             .FirstOrDefault()
    32.             // ignore whitespaces
    33.             .Trim();
    34.         myParsedHash = string.IsNullOrEmpty(myParsedHash) ? "" :
    35.             // get the right part of the string after what 'lookfor'. +1 because the substring index starts at zero
    36.             myParsedHash.Substring(lookFor.Length + 1);
    37.  
    38.         return myParsedHash;
    39.     }
    40. }
    41.  
    And here's a simple implementation to load the scene. I'm working with streaming asset bundles.

    Code (CSharp):
    1. LoadSceneMode loadSceneMode = LoadSceneMode.Single;
    2.  
    3. public IEnumerator LoadAssetBundle()
    4. {
    5.     if (!_myLoadedAssetBundle)
    6.     {
    7.         Debug.LogError("Could not load null asset bundle");
    8.         yield break;
    9.     }
    10.     string _sceneName;
    11.     if (_myLoadedAssetBundle.isStreamedSceneAssetBundle)
    12.     {
    13.         Debug.Log("Streaming asset in");
    14.  
    15.         string[] scenePaths = _myLoadedAssetBundle.GetAllScenePaths();
    16.         _sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePaths[0]);
    17.  
    18.         AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(_sceneName, loadSceneMode);
    19.  
    20.         while (!asyncLoad.isDone)
    21.         {
    22.             yield return null;
    23.         }
    24.     }
    25.     else
    26.     {
    27.         string[] assets = _myLoadedAssetBundle.GetAllAssetNames();
    28.  
    29.         Debug.Log("Getting all " + assets.Length + " assets in");
    30.  
    31.         Debug.LogError("Scene Asset Bundle should be streaming type. Prefab loading and instancing without a main scene is not supported by this function.");
    32.     }
    33. }
     
    Last edited: Feb 2, 2021
    mdrunk, ShantiB95 and BloodyXyber like this.
  27. FelixFrank

    FelixFrank

    Joined:
    Feb 25, 2021
    Posts:
    3
    I am actually looking for a solution like this. But I don't understand why it is necessary to download the asset bundle after checking for the hash. Why isn't it possible to compare the downloaded manifest's hash to the cached hash? If those are equal you don't even have to download the asset bundle completely. Or am I completely wrong?

    Thank you for your solution to this problem though. I would like to hear your opinion to my idea.

    - Felix
     
  28. BloodyXyber

    BloodyXyber

    Joined:
    Aug 17, 2019
    Posts:
    1
    So awesome. Thank you! Your code solves my problem and also introduced me to some pretty cool concepts :)
     
  29. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Hi,
    I want to apologize in advance for bringing up this old thread but it seems the most promising to me.

    I tried paulo_renans approach and it pretty much did what I expected. The only problem is I don't think that anything ever gets cached for me...
    I don't know why it does that because everything I have found so far tells me that UnityWebRequest is directly connected to the caching system and should cache assetbundles fully automatically.
    But the "FoundCache" bool in this script always returns false for me which leads me to believe that nothing is actually cached since every other Debug information seems correct to me.
    Most importantly it obtains the correct hash from the manifest which is the same everytime. So if the assetbundle was cached and the hash comparison returned true then the assetbundle shouldn't be downloaded over and over again but loaded from cache. Right now it when I download the assetbundle and load the scene - then go back and try the same again it doesnt't load from cache but always downlaods the whole thing again before loading the scene. How can I change this?

    Hopefully somebody is able to point me in the right direction what the problem could be...
    Thanks in advance!
     
  30. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    @MSachs, have you checked the C:\Users[USER]\AppData\LocalLow\Unity folder on Windows for your app's cached files? This helps determine if caching is working. If files are missing, there's a caching issue. If present, try running your app in Unity without internet to see if cached files load. Also, ensure your code uses a consistent hash string for each execution (it can be any string, not just one loaded from manifest file). Changing or empty hash strings will cause loading asset regardless of existing cache.
     
  31. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Thanks For the quick reply! I am on Mac do you know where the respective folder would be on there?
    Without internet connection nothing loads at all..
    The hash string is consistent. It doesn't change unless I am rebuilding the assetbundle.
     
  32. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    I think the correct path is '~/Library/Caches/Unity'. Regarding the hash string consistency, it's possible there's a logical error in the script causing this variable to change. It would be wise to use Debug.Log() to confirm it remains consistent between requests, just to be safe.
     
  33. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122
    Thanks! I found the folder but the only thing that is in there ist this "__info" document (screenshot) which seems to change every time I enter or exit play mode but not when pressing the download button. But it contains just some seemingly random numbers which don't change themselves...

    I already have a Debug.Log() which displays the hash. It is indeed the same every time.
     

    Attached Files:

  34. MSachs

    MSachs

    Joined:
    Nov 22, 2017
    Posts:
    122