Search code examples
c#apiunity-game-enginewebrequestunitywebrequest

Iterating over multiple UnityWebRequests


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


Solution

  • 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);
        }
    }