Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Asset Bundle download speed

Discussion in 'Asset Bundles' started by mobilizAR, Nov 29, 2018.

  1. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    11
    Hey guys,

    Just wanted to understand something better. So I have few asset bundles that I download from a CDN network. The speed that I get while downloading on iOS/Android Unity app is pretty slow. But if I try and download using Chrome browser on the same device, it takes about 6-7 seconds, whereas in Unity it takes about 60-70 seconds.

    Any idea why this is happening and/or how to increase the download speed for asset bundles in unity3d?

    I am using WebRequest.GetAssetBundle(url, version, crc) method to download it.

    Unity3d Version 2017.2.0f3

    Thank you.

    PS : I am using 2 servers for CDN download. Azure, and AWS. On both the same problem is happening.
     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    2,150
    GetAssetBundle() attaches DownloadHandlerAssetBundle to UWR, which loads asset bundles on the fly. Received bytes are fed to AssetBundle system, so it is slower than just a download. If you'd use Get() instead, the download should be faster, however it will give you much higher memory usage (entire bundle will be kept in memory), so it's trading one thing for another.
     
  3. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    11
    Hey, thanks for replying.

    I tried doing that also, still the download speed is very slow. Is there any other way or settings that I might have missed?
     
  4. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    11
    PS : I have a small check that keeps checking if the download.progress is stagnant for 10 seconds, and then aborts the web request so that the user isn't stuck there forever (used to happen before I implemented this)

    So usually, I get the abort request error because it is stagnant for 10 seconds.
     
  5. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    2,150
    Perhaps caching is involved? In UnityWebRequest implementation we disable caching, so bundle is always downloaded from server, you can enable caching by commenting one line of code in either WWWConnection.mm or UnityWebRequest.mm (depending on your Unity version).
     
  6. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    11
    The caching is definitely on, because once the Bundle is downloaded, the next time it takes 1 second to load from cache.

    Here is the code I use to download a normal bundle, below :

    Code (CSharp):
    1. string url = string.Format ("{0}{1}", a_strHostName, a_strAssetBundleName);
    2.         Hash128 version = a_version;
    3.         UnityWebRequest request = UnityWebRequest.GetAssetBundle (url, version, 0);
    4.         request.SendWebRequest ();
    5.         float counter = 0;
    6.         float m_fLastDownloadProgress = 0;
    7.         while (!request.isDone && request.error == null) {
    8.             if (OnCategoryDownloading != null)
    9.                 OnCategoryDownloading (cat, request.downloadProgress);
    10.             if (request.downloadProgress == m_fLastDownloadProgress) {
    11.                 counter += Time.deltaTime;
    12.                 if (counter > MAX_TIME_TO_WAIT_ON_SAME_PROGRESS) {
    13.                     Debug.Log ("Time!!!");
    14.                     request.Abort ();
    15.                 }
    16.             } else {
    17.                 m_fLastDownloadProgress = request.downloadProgress;
    18.                 counter = 0;
    19.             }
    20.             yield return null;
    21.         }
    22.         if (request.error != null) {
    23.             if (OnCategoryDownloadError != null)
    24.                 OnCategoryDownloadError (cat, request.error);
    25.         } else {
    26.             if (OnCategoryDownloadedSuccesssfully != null)
    27.                 OnCategoryDownloadedSuccesssfully (cat, request, url, version);
    28.         }
    29.         request.Dispose ();
    This is in a loop depending on how many "categories" a user selects.
     
  7. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    2,150
    How long does it take to download the bundle using UnityWebRequest.Get()?
    Is there a particular progress pattern?
     
  8. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    11
    So I wrote a small code (same as mentioned above) yesterday to download a bundle from Azure CDN and S3 CDN using GetAssetBundle and Get()

    Both took the same time on WiFi. 6 seconds total using GetAssetBundle(), and 4 seconds to download using Get() and 2 seconds to convert it to AssetBundle.

    No such progress pattern. I have my logs and analytics in place, and its all over the place. Most of the error outs are because of me aborting it manually since it was stagnant for 10 seconds. Sometimes I got an error saying "Unable to complete SSL connection", and "Cannot resolve destination host".
     
  9. AteoMarcel

    AteoMarcel

    Joined:
    Jan 5, 2017
    Posts:
    17
    We had the same problem with downloading an asset bundle as a file. (We used Webrequest.Get() from the start) it could be downloaded in 2 seconds in the browser and took 20-30 seconds on mobile (android and IOS).
    What we intend to use now is the .Net WebClient.

    Our code looks something like this:

    Code (CSharp):
    1.  
    2. using System.Net;
    3. using System.Security.Cryptography.X509Certificates;
    4. using System.Net.Security;
    5.  
    6. void safeFileUsingWebClient(string url, string path) {
    7.  
    8.             WebClient client = new WebClient();
    9.            // We need to authentificate on the server.
    10.             string auth = GetAuthString();
    11.             WebHeaderCollection header = new WebHeaderCollection {
    12.                 { "Authorization", auth }
    13.             };
    14.  
    15.             Uri uri = new Uri(url);
    16.          
    17.             // Might be needed had errors without this?!
    18.             Debug.Log(uri.AbsolutePath);
    19.             ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
    20.  
    21.             byte[]  data =client.DownloadData(uri);
    22.  
    23.             File.WriteAllBytes(path, data);
    24.             Log("File saved under " + path);
    25.         }
    26.  
    27.        private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors){
    28.             return true;
    29.         }
    The part with the RemoteCertificateValidationCallback was needed, since we run into an "TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a" error when we tried it without it.

    It is still not 100% working (we had some errors with "404 file not found" with this implementation (which we never had with the unity webrequest).
    However, it takes 5 seconds instead of 20-30 to download the file with the new webclient.