Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Help Wanted Use unitywebrequest without coroutine

Discussion in 'Scripting' started by chengwang2077, Jul 21, 2020.

  1. chengwang2077

    chengwang2077

    Joined:
    Nov 23, 2019
    Posts:
    131
    In order to use unitywebrequest, my code is full of coroutines and delegates. These grammars make my code very complicated. UniRx allows me to use network requests in a concise syntax, but it does not support UnityWebRequest. What should I do?
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    5,627
    You are not required to use coroutines with UnityWebRequest. You can do something like this if you really wanted to:

    Code (CSharp):
    1. UnityWebRequestAsyncOperation asyncOperation;
    2.  
    3. void Start() {
    4.   asyncOperation = UnityWebRequest.Get("myurl.com").SendWebRequest();
    5. }
    6.  
    7. void Update() {
    8.   if (asyncOperation.isDone) {
    9.     // Done!
    10.     string result = asyncOperation.webRequest.downloadHandler.text;
    11.   }
    12. }
     
    chengwang2077 likes this.
  3. AnthonySharp

    AnthonySharp

    Joined:
    Apr 11, 2017
    Posts:
    88
    EDIT: forgive the awful code formatting

    I've never used UniRx before but I'm working on a project right now that uses a bunch of networking so...

    Because networking code inevitably involves sending and requesting lots of different kinds of data and then doing all sorts of different things to that data, it's somewhat unavoidable that it will end up being quite complicated in terms of how those networks requests are handled. But there are a few ways to simplify things.

    As PraetorBlue says, you don't have to use coroutines. I hadn't thought about using the Update() function for networking calls, which is actually quite clever. But I think the only issue is that once you chuck in your error handling etc, you might find it turns out to be just as complicated and untidy as using coroutines anyway.

    Your second option is to simply to use synchronous networking calls. This would usually be considered bad practice (and will actually cause your code to freeze if there is no network connection etc and you don't handle that properly), but the upshot is that it is very easy to manage IF you can get away with it. It's also a good solution for networking calls that don't require a value to be returned (because you can just send it and forget about it, rather than having to wait around for a response). For example you can create a template function:

    Code (CSharp):
    1. public static void DoPostRequest(string url, string[] fields, string[] values)
    2.     {
    3.         WWWForm form = new WWWForm();
    4.  
    5.         for (int i = 0; i < fields.Length; i++)
    6.         {
    7.             form.AddField(fields[i], values[i]);
    8.         }
    9.  
    10.         UnityWebRequestAsyncOperation wr = UnityWebRequest.Post(url, form).SendWebRequest();
    11.     }
    It then becomes very easy to call it however you like:

    Code (CSharp):
    1. public static void BlockUser(string blockwhom)
    2.     {
    3.         DoPostRequest("https://www.myrandomserver.co.uk/blocks/blockuser.php",
    4.             new string[] { "blockwhom" },
    5.             new string[] { blockwhom } );
    6.     }
    Even asynchronous calls don't necessarily have to be complicated:

    Code (CSharp):
    1. IEnumerator DownloadImageAndApplyToRawImage(string imageid, RawImage therawimage)
    2.     {
    3.         UnityWebRequest www = UnityWebRequestTexture.GetTexture("https://www.myserver.com/downloadimage.php?imageid=" + imageid);        
    4.        
    5.         yield return www.SendWebRequest();
    6.  
    7.         if (www.isNetworkError || www.isHttpError) Debug.Log("Network error: " + www.error);
    8.         else if(therawimage) therawimage.texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
    9.         // garbage collection ?
    10.     }
    After that you can call them just like any other function.

    I was taking a look at possibly using the async operator to simplify things but supposedly that is not something that is straightforward to implement with UnityWebRequest because it is not something that comes as standard with Unity (https://forum.unity.com/threads/do-...-and-unitywebrequest-with-async-await.589870/). Not even sure how helpful it would be anyhow, since I've never used it.

    If you want to get really serious, you could even create some kind of download/upload handler class that stores retrieved networking data. But, again, whether that would result in "simpler" code is debatable.

    Perhaps someone with more experience than I might have more of an idea about what might be useful for you.
     
    chengwang2077 likes this.
  4. crevelop

    crevelop

    Joined:
    Nov 9, 2010
    Posts:
    13
    Hey guys,

    You might find my UnityWebRequest async tutorial useful.



    I'm doing just that, using UnityWebRequest within an async function instead of coroutines.

    The tutorial expands into deserializing JSON, using dependency injection and other perks.

    I hope it helps, cheers :)
     
unityunity