Search Unity

UnityWebRequest with async/await freezes Editor

Discussion in 'Scripting' started by stefanob, Feb 11, 2021.

  1. stefanob

    stefanob

    Joined:
    Nov 26, 2012
    Posts:
    68
    Hello,

    I'm trying to UnityWebRequest using async/await in a custom Editor.
    At the end of the download progress the editor freezes for a while (depending on the file size up to several minutes).
    I'm calling this function in OnGUI() on Button click:

    Code (CSharp):
    1. public static async void LoadFile(string file)
    2. {
    3.     Task<byte[]> loadTask = Task_LoadFile(file);
    4.     byte[] bytes= await loadTask;
    5.     // the file seems to download fine and nothing is blocked. After the download the editor freezes.
    6. }
    7.  
    8. private static async Task<byte[]> Task_LoadFile(string file)
    9. {
    10.     WWWForm form = new WWWForm();
    11.     form.AddField("filename", file);
    12.  
    13.     UnityWebRequest www = UnityWebRequest.Post("www.url.com/get_file.php", form);
    14.  
    15.     UnityWebRequestAsyncOperation operation = www.SendWebRequest();
    16.     while (!operation.isDone)
    17.     {
    18.         await Task.Delay(100);
    19.     }
    20.     if (www.error == null)
    21.     {
    22.         return www.downloadHandler.data;
    23.     }
    24.     else
    25.     {
    26.         Debug.LogError(www.error);
    27.     }
    28.  
    29.     return null;
    30. }
    Any ideas? Thanks!
     
    ENOUGH- likes this.
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,735
    UnityWebRequestAsyncOperation has a completed event. Connect a handler to it and you will not need to bother with tasks.
     
  3. stefanob

    stefanob

    Joined:
    Nov 26, 2012
    Posts:
    68
    This doesn't help with my problem. Same effect. Right after the file is downloaded everything freezes for a while. The download works, the file is there but something seems to happen in the background.
    I also reduced everything to a simple Get call with a test file (200MB):

    Code (CSharp):
    1.  
    2. BundleWebRequest = UnityWebRequest.Get("http://www.url.com/testfile.zip");
    3.             UnityWebRequestAsyncOperation operation = BundleWebRequest.SendWebRequest();
    4.             operation.completed += BundleOperation_CompletedHandler;
    5.         }
    6.  
    7.         private static void BundleOperation_CompletedHandler(AsyncOperation obj)
    8.         {...
    9.  
    Edit: I'm using Unity 2019.2.17f1
     
    Last edited: Feb 11, 2021
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    200mb of data all at once is probably what is choking you up... I forget if Unity supports chunked transfers to get the pieces one by one and stick them somewhere, like write them to disk. If Unity does support this, it will be a type of downloader that you iteratively call.
     
  5. stefanob

    stefanob

    Joined:
    Nov 26, 2012
    Posts:
    68
    UnityWebRequest has a chunkedTransfer property but it's only for uploading data.
     
  6. stefanob

    stefanob

    Joined:
    Nov 26, 2012
    Posts:
    68
    I ended up using HttpClient instead. Works much better.
     
  7. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,735
    Ah, misread a bit. It freezes for some time, that does make sense if you files are so huge. The question is - what do you do with downloaded data? If you save it to file, then you should be using DownloadHandlerFile.
     
    stefanob likes this.
  8. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    Yeah unity does have a special download handler for that. It's called DownloadHandlerFile.

    When UnityWebRequest.Get is used, it will by default be a normal DownloadHandler. Which means it is loading all data (bytes[]) into memory.
    But overriding the DownloadHandler with DownloaderHandlerFile will download the file in chunks. Also not loading it into memory but only allocating the buffer size.

    https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Networking.DownloadHandlerFile.html
    "This specialized download handler writes all downloaded bytes directly to file. This can help avoid high memory usage. Note that you cannot get any data out of this download handler; you are expected to work with resulting file after the download is finished."
     
    stefanob likes this.
  9. stefanob

    stefanob

    Joined:
    Nov 26, 2012
    Posts:
    68
    Ah yes that was it.
    In the beginning I used Filestream.write() after loading to save the file. First I thought the writing blocks the Editor. But the problem persisted after I removed it. Didn't know about DownloadHandlerFile.

    Thanks! Works very smooth now.
     
  10. samtcs

    samtcs

    Joined:
    Dec 14, 2022
    Posts:
    3
    Hi, Could you please post the working code. I am new to unity. Thanks in advance.