Search Unity

Loading AssetBundle from Streaming Assets to Cache via UnityWebRequestAssetBundle

Discussion in 'Editor & General Support' started by studentutu, Dec 31, 2018.

  1. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    Hi Everyone,
    I have implemented logic for loading Assetbundles from Cache based on the Directory names (if directory "myBundle" has 0 directories inside - it is empty, otherwise you safely load "myBundle" with UnityWebRequestAssetBundle( "", new CachedAssetBundle{name = "myBundle"}, 0 )) which will load it from Cache (exacly the same directory name as in CachedAssetBundle name ).

    The code for loading from Streaming Assets to Cache is like so:
    Code (CSharp):
    1. private IEnumerator LoadBundlefromStreamingAsset(string pathFromStreamingAssets, string bundleName)
    2.         {
    3.             string pathToBundle = "file:///" + Application.streamingAssetsPath + "/" + pathFromStreamingAssets;
    4.             Log(" Path in Streaming Assets : " + pathToBundle);
    5.             using (UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(pathToBundle, 0, 0))
    6.             {
    7.                 request.SendWebRequest();
    8.                 yield return request;
    9.                 yield return new WaitForSeconds(0.25f);
    10.                 AssetBundle bundle = ((UnityEngine.Networking.DownloadHandlerAssetBundle)request.downloadHandler).assetBundle;
    11.                 // Remove from memory to allow custom ( based on Caching) logic do its job
    12.                 bundle.Unload(true);
    13.             }
    14. }
    Everything works perfectly on Windows and Mac, but when I'm using it on Android, after the first use of the LoadBundlefromStreamingAsset coroutine, using it the second time will result in an error thrown by Unity.

    Is there any way around on how to load AssetBundle from StreamingAssets to cache even on Android?
     
  2. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121

    It is appeared to be a bug with Caching - when you make a call to ClearAllCache on the Mobile (From the App itself) and then use the above, it all works flawlessly!
     
  3. alexeyzakharov

    alexeyzakharov

    Joined:
    Jul 2, 2014
    Posts:
    508
    Did you try loading without "file:///" prefix to the path?
    AFAIK Application.streamingAssetsPath already contains it and doubling it might cause issues with caching artifacts resolution.
     
    studentutu likes this.
  4. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    Yes, and yes it was a problem with the file:/// but now, again on Android, I have another Issue :
    Code (CSharp):
    1.  <Color=Blue>  Loading From Streaming Assets into cache: jar:file:///data/app/com.kau.wrod-1/base.apk!/assets/en/Android/bigdataobject </Color>
    2. 01-03 12:13:05.831 10855 10886 I Unity   :
    3. 01-03 12:13:05.831 10855 10886 I Unity   : (Filename: ./Runtime/Export/Debug.bindings.h Line: 43)
    4. 01-03 12:13:05.831 10855 10886 I Unity   :
    5. 01-03 12:13:07.002 10855 10886 E Unity   : InvalidOperationException: Cannot get content from an unfinished UnityWebRequest object
    6. 01-03 12:13:07.002 10855 10886 E Unity   :   at UnityEngine.Networking.DownloadHandler.GetCheckedDownloader[T] (UnityEngine.Networking.UnityWebRequest www) [0x0001d] in <6aaad1c9744e454b96e73044b9276939>:0
    7. 01-03 12:13:07.002 10855 10886 E Unity   :   at UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent (UnityEngine.Networking.UnityWebRequest www) [0x00001] in <deee6915c84b4f0ea72fc147a614158a>:0
    8. 01-03 12:13:07.002 10855 10886 E Unity   :   at KAUGamesLviv.Services.Bundles.BundleScriptable`1+<LoadBundlefromStreamingAsset>c__Iterator0[T].MoveNext () [0x000f1] in <736923169ae449198904e7e23151e2c3>:0
     
    alexeyzakharov likes this.
  5. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    Found a mistake :
    I have used
    Code (CSharp):
    1. UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(request);
    to retrieve the content. You should use casting on the attached downloadhandler of the request. This ensures that the content and request are on the same object.
     
    Last edited: Jan 3, 2019
    alexeyzakharov likes this.
  6. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    No, your original code is wrong. Instead of yield returning UnityWebRequest you should yield areturn the AsyncOperation returned by SendWebRequest(). You code assumes the load time which is too low for Android.
     
  7. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    Is it? The request itself is exactly the same asyncoperation, isn't it? I currently use both yields, and only when I cast to
    ((UnityEngine.Networking.DownloadHandlerAssetBundle)request.downloadHandler).assetBundle; the code works without any errors.
     
  8. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    No, it's not. yield returning UWR itself will only suspend coroutine until next frame. Your code relies entirely on timing, so it manages to download the bundle within given time frame on Desktop, but on Android it's slower, so the bundle is not yet loaded when your try to access it.
     
  9. studentutu

    studentutu

    Joined:
    Oct 22, 2017
    Posts:
    121
    Got it! thank you!. Also, unrelated shader question, do you know any way on how to retrieve FrameBuffer ? (to use the previous SV_TARGET as a texture, something like a Grabpass, but without the Grabpass)? I have seen how people have made a hack - in first pass use surface shader to write into another texcoord, and in second pass use simple vertex/fragment program to get those texcoord.
     
    Last edited: Jan 25, 2019
  10. madhu_unity425

    madhu_unity425

    Joined:
    Oct 25, 2018
    Posts:
    8
    can anyone help me how to download the images from the server to the streaming assets folder
     
  11. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Streaming assets folder should be considered read only. It's not necessary true, but on it might be and on some platforms it always is read only.
    You should download them to persistent data path.