Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity WebGL UnityWebRequest Bad Body Data

I have a Unity game hosted on a web publishing platform. This game connects to several APIs, including Microsoft PlayFab, Google Analytics, and our own back end server. Sometimes (very rarely, less than 0.1% of the time) the game fails to connect to any of these services, and I'm not sure why. I have never been able to reproduce this locally. We currently have not been able to isolate it to a particular region, due to its rarity. It seems to affect specific computers/households. Multiple browsers on the same computer running the game will fail the same way. Sometimes multiple computers in the same household will also be affected.

Microsoft and Google both return a 400 error, and our own service replies with a 400. Unity notes that an 'Unknown Error' occurred during the UnityWebRequest.

I cannot look at the data sent/received with Microsoft or Google, but I can look at our own server logs, and things get strange. The UnityWebRequest is making it to our service, which is hosted on AWS and proxied by CloudFlare. The URL is correct, but the request body seems completely bizarre:

"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\b\u0000\u0000\u0000\u0000\u0000\u0000\u0000xך\u0000\u0000\u0000\u0000\u0000`ך\u0000�\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000`ך\u0000!\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0010\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"

That's the contents of the request body. If I grab the bytes (assuming a UTF8 encoded string) then I get the following:

byte[72] { 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 120, 215, 154, 0, 0, 0, 0, 0, 96, 215, 154, 0, 239, 191, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 215, 154, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

My first guess was that AWS/CloudFlare/Google are perhaps blocked by certain firewalls or regions, but if that were the case I would not expect anything to have made it to our own AWS server to analyze. So now I am not sure...

Here's the relevant Unity (2018.2.21f1) code:

UnityWebRequest www = UnityWebRequest.Post(uri, body);
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
uploadHandler.contentType = "application/json";
www.uploadHandler = uploadHandler;
www.SetRequestHeader("Content-Type", "application/json");

yield return www.Send();

if (www.isNetworkError || www.isHttpError)
{
    Log(ELoggingLevel.Error, "Error while sending data: [{0}]", www.error);
}
else
{
    var contents = www.downloadHandler.text;
    // do useful stuff here
}

The logger does fire, so either isNetworkError or isHttpError are true.

[Error]: Error while sending data: [Unknown Error]

Does anyone have any thoughts on what is going on? Does anyone recognize that data being logged by the server? It appears like my Unity game just refuses to send any type of reasonable data in some sort of rare situation.

Edit: I logged the content type on the server, and am correctly getting application/json, which would suggest a solid amount of the data is arriving properly. The body data is also identical across multiple users. Unity is probably only returning an error because of the 400 being returned by the server.

like image 301
Giawa Avatar asked Oct 16 '25 14:10

Giawa


1 Answers

I have struggled with the exact same error. Clients using my app received a 400 or Unknown Error rarely. Locally I could not reproduce this. However it was not with an upload, but with several (different) post requests. I use a different server provider as you do though.

I tried looking for a reason (and answer) but could never find one.

I did manage to create a workaround/ solution for it though. It seems that if you execute the same action 0.1 second later, it would pass without problem. So I suggest implementing something like the following.

int tryCounts = 3;

for (int i = 0; i < tryCounts; i++)
{
    UnityWebRequest www = UnityWebRequest.Post(uri, body);
    UploadHandlerRaw uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
    uploadHandler.contentType = "application/json";
    www.uploadHandler = uploadHandler;
    www.SetRequestHeader("Content-Type", "application/json");

    yield return www.Send();

    if (www.isNetworkError || www.isHttpError)
    {
        Log(ELoggingLevel.Error, "Error while sending data: [{0}]", www.error);
        yield return new WaitForSecondsRealtime(0.15f); 
    }
    else
    {
        var contents = www.downloadHandler.text;
        // do useful stuff here
        break;
    }
}

This simple solution fixed all my problems. I still see an unknown error pop in my database errorlog from time to time. Since I also log the trycount, I can confirm that I never had it pop up twice in a row.

like image 84
Immorality Avatar answered Oct 18 '25 05:10

Immorality



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!