0

I have been trying to get some API communication to work. I am using UnityWebRequests because I want to build as WebGL (I tried System.Net.WebRequest, which worked in game-mode, but was not compatible with WebGL). It might just be a problem of Coroutines, but I'll show you in semi-pseudo what I have so far and what my problem is:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;

public class scking : MonoBehaviour
{

    string tempText;
    string getUri = "https://api.opensensors.com/getProjectMessages";
    string jwtToken = "someToken";

    private void Start()
    {
        pullAllData();
    }

    IEnumerator GetDataRequest(string currentDateString, string nextDateString, string sensorID)
    {
        string requestParam = "myparameters: " + nextDateString + sensorID; // simplified dummy parameters

        using (UnityWebRequest webRequest = UnityWebRequest.Get(requestParam))
        {
            webRequest.SetRequestHeader("Authorization", "Bearer " + jwtToken);
            webRequest.SetRequestHeader("Content-Type", "application/json");

            yield return webRequest.SendWebRequest();

            // from unity api example
            string[] pages = getUri.Split('/');
            int page = pages.Length - 1;

            if (webRequest.isNetworkError)
            {
                Debug.Log(pages[page] + ": Error: " + webRequest.error);
            }
            else
            {
                Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
            }

            // getting the data i pulled out of the coroutine for further manipulation
            this.tempText = webRequest.downloadHandler.text;

            // show whats been pulled
            print(this.tempText);
        }
    }

    void pullAllData()
    {
        int allDaysCount = 10;
        List<int> sensorIds; // initialized with some ids

        for(int i = 0; i < allDaysCount - 1; i++)
        {
            for(int j = 0; j < sensorIds.Count; j++)
            {
                StartCoroutine(GetDataRequest(i, i + 1, sensorIds[j]));

                // show whats been pulled
                print(this.tempText);

                // parse json string this.tempText etc.
            }
        }

    }
}

The output is (sorted by time)

from print in pullAddData:null

and then next from print in the coroutine: jsonItem

Basically the Coroutine takes too long and is too late for my loop to continue, and because I get a null, I of course can't parse or manipualte my data. Or maybe my entire work is flawed, in that case, how to do this propperly?

Really thankful for any help on this. Kind, Philipp

  • you need to print the result after you get it not assume its fairly instamatic – BugFinder Nov 21 '19 at 10:25
  • 1
    ```StartCoroutine``` will only start the pseudo thread and return immediately. So if you try to print the result of your request in the next line after only starting the request it will never have already received the result. The parsing and manipulation of the data must happen in ```GetDataRequest```, after the ```yield``` statement. This is where you can be sure that the server response has been received. – Benjamin Zach Nov 21 '19 at 10:27
  • 1
    You mean like this: [Wait for all requests to continue](https://stackoverflow.com/questions/58827893/wait-for-all-requests-to-continue/58830910#58830910)(parallel) ? – derHugo Nov 21 '19 at 11:36
  • Thank you @BenjaminZach great idea. It actually works well as you said. I still feel like there must be a more charming solution to this. – Philipp Siedler Nov 21 '19 at 11:42
  • @derHugo This is great! I guess in my mind I would want to do each request step by step, wait for the data to come in, process it, store it in some list and continue with the next UnityWebRequest. – Philipp Siedler Nov 21 '19 at 11:44

1 Answers1

1

If you want to wait for them parallel checkout my answer to Wait for all requests to continue


If you rather wanted to still wait for them one-by-one you can simply wrap them into one bigger Coroutine:

void pullAllData()
{
    int allDaysCount = 10;
    List<int> sensorIds; // initialized with some ids

    // start the "parent" Coroutine
    StartCoroutine(GetAllData(allDaysCount, sensorIds));
}

IEnumerator GetAllData(int allDaysCount, List<int> sensorIds)
{
    for(int i = 0; i < allDaysCount - 1; i++)
    {
        for(int j = 0; j < sensorIds.Count; j++)
        {
            // Simply run and wait for this IEnumerator
            // in order to execute them one at a time
            yield return GetDataRequest(i, i + 1, sensorIds[j]);

            // show whats been pulled
            print(this.tempText);

            // parse json string this.tempText etc.
        }
    }

    // Maybe do something when all requests are finished and handled
}

IEnumerator GetDataRequest(string currentDateString, string nextDateString, string sensorID)
{
    string requestParam = "myparameters: " + nextDateString + sensorID; // simplified dummy parameters

    using (UnityWebRequest webRequest = UnityWebRequest.Get(requestParam))
    {
        webRequest.SetRequestHeader("Authorization", "Bearer " + jwtToken);
        webRequest.SetRequestHeader("Content-Type", "application/json");

        yield return webRequest.SendWebRequest();

        // from unity api example
        string[] pages = getUri.Split('/');
        int page = pages.Length - 1;

        if (webRequest.isNetworkError)
        {
            Debug.Log(pages[page] + ": Error: " + webRequest.error);
        }
        else
        {
            Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
        }

        // getting the data i pulled out of the coroutine for further manipulation
        this.tempText = webRequest.downloadHandler.text;

        // show whats been pulled
        print(this.tempText);
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115