Obtain data from UnityWebRequest while still downl

2019-03-06 19:12发布

I have this code that makes a REST call:

public IEnumerator GetCooroutine(string route)
{
    string finalURL = URL + route;
    UnityWebRequest www = UnityWebRequest.Get(finalURL);
    yield return www.SendWebRequest();

    if (www.isNetworkError || www.isHttpError) {
        Debug.Log(www.error);
    }
    else {
        Debug.Log("GET succesfull. Response: " + www.downloadHandler.text);
    }
}

I need to access the data or body of the request while they are receiving, and use it for other stuff. I don't want to wait until it has finished receiving them before accessing them.

If I use yield, the code waits until the send finishes it's execution, and I don't want that.

1条回答
SAY GOODBYE
2楼-- · 2019-03-06 19:15

It is possible to do it with UnityWebRequest but you have to perform extra work. The secret is to use DownloadHandlerScript with UnityWebRequest.

Create a separate class and make it derive from DownloadHandlerScript instead of MonoBehaviour. In the example below, I will call it CustomWebRequest. Override the bool ReceiveData(byte[] data, int dataLength), void CompleteContent() and the void ReceiveContentLength(int contentLength) functions inside it.

Here is an example of the CustomWebRequest class:

public class CustomWebRequest : DownloadHandlerScript
{
    // Standard scripted download handler - will allocate memory on each ReceiveData callback
    public CustomWebRequest()
        : base()
    {
    }

    // Pre-allocated scripted download handler
    // Will reuse the supplied byte array to deliver data.
    // Eliminates memory allocation.
    public CustomWebRequest(byte[] buffer)
        : base(buffer)
    {
    }

    // Required by DownloadHandler base class. Called when you address the 'bytes' property.
    protected override byte[] GetData() { return null; }

    // Called once per frame when data has been received from the network.
    protected override bool ReceiveData(byte[] byteFromServer, int dataLength)
    {
        if (byteFromServer == null || byteFromServer.Length < 1)
        {
            Debug.Log("CustomWebRequest :: ReceiveData - received a null/empty buffer");
            return false;
        }

        //Do something with or Process byteFromServer here


        return true;
    }

    // Called when all data has been received from the server and delivered via ReceiveData
    protected override void CompleteContent()
    {
        Debug.Log("CustomWebRequest :: CompleteContent - DOWNLOAD COMPLETE!");
    }

    // Called when a Content-Length header is received from the server.
    protected override void ReceiveContentLength(int contentLength)
    {
        Debug.Log(string.Format("CustomWebRequest :: ReceiveContentLength - length {0}", contentLength));
    }
}

And to use it to start the download, just create new instance of UnityWebRequest and use CustomWebRequest as the downloadHandler before calling the SendWebRequest function. No coroutine required for this and you don't even have to yield anything. This is how to do it:

UnityWebRequest webRequest;
//Pre-allocate memory so that this is not done each time data is received
byte[] bytes = new byte[2000];

void Start()
{
    string url = "http://yourUrl/mjpg/video.mjpg";
    webRequest = new UnityWebRequest(url);
    webRequest.downloadHandler = new CustomWebRequest(bytes);
    webRequest.SendWebRequest();
}

That's it.

  • When Unity first makes the request, ReceiveContentLength(int contentLength) is called. You can use the contentLength parameter to determine the total number of bytes you will receive from that request.

  • The ReceiveData function is called each time new data is received and from that function, you can access that current data from the byteFromServer parameter and the length of it from the dataLength parameter.

  • When Unity is done receiving data, the CompleteContent function is called.

查看更多
登录 后发表回答