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?
You are not required to use coroutines with UnityWebRequest. You can do something like this if you really wanted to:
UnityWebRequestAsyncOperation asyncOperation;
void Start() {
asyncOperation = UnityWebRequest.Get("myurl.com").SendWebRequest();
}
void Update() {
if (asyncOperation.isDone) {
// Done!
string result = asyncOperation.webRequest.downloadHandler.text;
}
}
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:
public static void DoPostRequest(string url, string[] fields, string[] values)
{
WWWForm form = new WWWForm();
for (int i = 0; i < fields.Length; i++)
{
form.AddField(fields[i], values[i]);
}
UnityWebRequestAsyncOperation wr = UnityWebRequest.Post(url, form).SendWebRequest();
}
It then becomes very easy to call it however you like:
public static void BlockUser(string blockwhom)
{
DoPostRequest("https://www.myrandomserver.co.uk/blocks/blockuser.php",
new string[] { "blockwhom" },
new string[] { blockwhom } );
}
Even asynchronous calls don’t necessarily have to be complicated:
IEnumerator DownloadImageAndApplyToRawImage(string imageid, RawImage therawimage)
{
UnityWebRequest www = UnityWebRequestTexture.GetTexture("https://www.myserver.com/downloadimage.php?imageid=" + imageid);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError) Debug.Log("Network error: " + www.error);
else if(therawimage) therawimage.texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
// garbage collection ?
}
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 ( Do we have to use WebRequest and HttpWebRequest instead of WWW and UnityWebRequest with async/await ). 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.
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
the cleanest implementation i have ever seen so far… i wish u do more videos like these
thanks
I am following this same Tutorial, but my machine is locking up because of the while statement. What am I doing wrong?
The URL is valid and returns if I step through with the debugger, but this doesn’t work otherwise.
public async Task<T> Get<T>(string value,string url)
{
url = $"{url}&query={value}&timezone_module=1";
var request = UnityWebRequest.Get(url);
request.SetRequestHeader("Content-Type", "json/application");
var operation = request.SendWebRequest();
while(!operation.isDone)
{
await Task.Yield();
}
var jsonResonse = request.downloadHandler.text;
if (request.result != UnityWebRequest.Result.Success)
{
Debug.Log($"Failed: {request.error}");
}
try
{
var result = JsonConvert.DeserializeObject<T>(jsonResonse);
Debug.Log($"Success: {request.downloadHandler.text}");
return result;
}
catch(Exception ex)
{
Debug.LogError($"Could not parse response {jsonResonse}.{ex}");
return default;
}
}
public void SetLocation(string locationInfo)
{
_location = apiClient.Get<Location>(locationInfo,apiClient.LocationURL).Result;
Debug.Log(_location.Data[0].Name.ToString());
}