Reputation: 664
So right now I am making HTTP requests to a server, but I need to send a GET request with some JSON data as well. What I am doing right now "works", but is terrible because it drops down to nearly 15 FPS each request. Here is my code.
Here is my GET Query:
{
"query": {
"match_all": {}
},
"size": 1,
"sort": [{
"@timestamp": {
"order": "desc"
}
}]
}
Here is my start method:
void Start()
{
queryString = File.ReadAllText(Application.streamingAssetsPath +"/gimmeData.json");
StartCoroutine(SetJsonData());
}
Here is the co-coutine I have set up to actually do the requests:
private IEnumerator SetJsonData()
{
// Make a new web request with the .net WebRequest
request = WebRequest.Create(elk_url);
yield return null;
request.ContentType = "application/json";
request.Method = "POST";
buffer = Encoding.GetEncoding("UTF-8").GetBytes(queryString);
// Put this yield here so that I get higher FPS
yield return null;
requestStream = request.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Close();
// Again this is about getting higher FPS
yield return null;
response = (HttpWebResponse)request.GetResponse();
// Wait until we have all of the data we need from the response to continue
yield return requestStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(requestStream);
// Set my string to the response from the website
JSON_String = reader.ReadToEnd();
yield return null;
// Cleanup the streams and the response.
reader.Close();
requestStream.Close();
response.Close();
yield return null;
// As long as we are not null, put this in as real C# data
if (JSON_String != null)
{
// Wait until we finish converting the string to JSON data to continue
yield return StartCoroutine(StringToJson());
}
if(dataObject != null)
{
// Send the data to the game controller for all of our hits
for(int i = 0; i < dataObject.hits.hits.Length; i++)
{
StartCoroutine(
gameControllerObj.CheckIpEnum(dataObject.hits.hits[i]._source));
}
}
// As long as we didn't say to stop yet
if (keepGoing)
{
yield return null;
// Start this again
StartCoroutine(SetJsonData());
}
}
I have all those "yield return null"s in there because it improved the FPS from what it already was.
How can I optimize this? Is there a better way to make a web request that can also send GET data with it? I know that UnityWebRequest is a thing, but that does not allow me to send the JSON data that I have.
Upvotes: 0
Views: 1989
Reputation: 3789
Note: The code in your question is performing a POST, not a GET. There's no such thing as 'get data'.
The following suggestion is equivalent from the server's point of view.
If you actually want a GET request - i.e. something totally different to what your code does - see the end of this answer.
Wait until we have all of the data
- This is where your framerate comes to die. This is because the Unity main thread - essentially your entire game - will wait for the server to respond with all of the data.
In short, that's just because of how coroutines work - they're very different from threads.
The general approach in Unity is to use WWW in a coroutine instead. Internally Unity runs the actual request on a separate thread and that coroutine just checks in on the progress every so often:
POST, matching your question's code:
// Build up the headers:
Dictionary<string,string> headers = new Dictionary<string,string>();
// Add in content type:
headers["Content-Type"] = "application/json";
// Get the post data:
byte[] postData = Encoding.GetEncoding("UTF-8").GetBytes(queryString);
// Start up the reqest:
WWW myRequest = new WWW(elk_url, postData, headers);
// Yield until it's done:
yield return myRequest;
// Get the response (into your JSON_String field like above)
// Don't forget to also check myRequest.error too.
JSON_String = myRequest.text;
// Load the JSON as an object and do magical things next.
// There's no need to add extra yields because
// your JSON parser probably doesn't support chunked json anyway.
// They can cover a few hundred kb of JSON in an unnoticeable amount of time.
....
GET, matching your question:
// Start up the reqest (Total guess based on your variable names):
// E.g. mysite.com/hello?id=2&test=hi
WWW myRequest = new WWW(elk_url + "?"+queryString);
// Yield until it's done:
yield return myRequest;
// Get the response
JSON_String = myRequest.text;
....
Upvotes: 4