Unity WebGL UnityWebRequest数据处理

时间:2018-09-26 09:50:39

标签: c# unity3d networking unity-webgl

我对Unity WebGL以及从UnityWebRequests下载的数据的处理方式有疑问。在独立版本中,我正在等待$ ./ddd sizeof RXDATA = 80 $ 下载的数据,然后对其进行json序列化。之后,我执行while (!async.isDone) { }。这样,当首先完全处理完收益返回后,就可以对数据进行处理。但是在WebGL中,yield return null;是不允许的,就像在WebGL Networking中解释的正式文档中一样。

那么解决此问题的最佳方法是什么?处理完成后,是否需要在同一协程中调用处理程序?但是后来我仍然遇到了用已处理数据创建gameObjects的问题,因为您只能在unity本身的主线程中创建gameObjects。

有人遇到同样的问题并找到了解决方案吗?

谢谢!

更新: 这是完整的代码示例:

while (!async.isDone) { }

Update2:

由于仍然不清楚,这里是另一个示例:

private IEnumerator m_GetUserToken(string accesscode, string password)
{
    UnityWebRequest request = new UnityWebRequest(v_ServerIP + "api-token-auth/", "POST");

    byte[] bodyRaw = Encoding.UTF8.GetBytes("{\"username\":\"" + accesscode + "\", \"password\":\"" + password + "\"}");
    request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    request.SetRequestHeader("Content-Type", "application/json");
    request.chunkedTransfer = false;
    UnityWebRequestAsyncOperation async = request.SendWebRequest();

    while (!async.isDone) { }

    if (request.isNetworkError || request.isHttpError)
    {
        v_TokenSuccess = false;
        Debug.Log("Token Error: " + request.error);
        Debug.Log("Token Response Code: " + request.responseCode);
    }
    else
    {
        v_UserToken = JsonUtility.FromJson<UserToken>(request.downloadHandler.text);
        v_TokenSuccess = true;
    }
    yield return Timing.WaitForOneFrame;
}

因此,在调用#Main Thread string s = ""; StartCoroutine(functionname); Debug.Log(s); #Coroutine private IEnumerator functionname(){ downloadTextfromUrl while(!downloadFinished) {yield return null} s = downloadText; } 之后,将调用yield return null,由于尚未调用Debug.Log(s),因此s仍然为空。

1 个答案:

答案 0 :(得分:2)

在等待UnityWebRequest属性完成的async.isDone请求的同时,您必须在while循环内屈服。您当前的代码可能会导致Android设备上的无限循环或使下载失败。您链接的文档说您可以使用while (!async.isDone) ,但是您必须屈服。这不仅适用于WebGL,还适用于每个平台。

替换

while (!async.isDone) { }

使用

while (!async.isDone) { yield return null; }

这将使while循环在每一帧执行一次,并检查async.isDone是否为真,而不是阻塞整个程序。


注意:

进行第二次编辑后,您似乎还想访问该功能之外的下载数据。例如,您要执行以下操作:

StartCoroutine(functionname());
//then use the downloaded data
Debug.Log(downloaded_data);

您有两种方法可以做到这一点:

1 。像我上面那样用yield return StartCoroutine(functionname())产生coorutine函数。这必须通过另一个协程函数完成:

请求功能:

string v_UserToken;

IEnumerator m_GetUserToken(string url)
{
    UnityWebRequest request = UnityWebRequest.Get(url);
    UnityWebRequestAsyncOperation async = request.SendWebRequest();
    while (!async.isDone) { yield return null; }

    if (request.isNetworkError || request.isHttpError)
    {
        v_UserToken = request.error;
    }
    else
    {
        v_UserToken = request.downloadHandler.text;
    }
}

然后在调用它之后等待它完成:

IEnumerator AnotherCoroutineFunc()
{
    //Call and wait for the m_GetUserToken coroutine to finish
    yield return StartCoroutine(m_GetUserToken("YourURL"));
    //You can now use the v_UserToken variable
    Debug.Log(v_UserToken);
}

2 。您可以使用Action等待它。

带有Action的请求函数:

IEnumerator m_GetUserToken(string url, Action<string> result)
{
    UnityWebRequest request = UnityWebRequest.Get(url);
    UnityWebRequestAsyncOperation async = request.SendWebRequest();
    while (!async.isDone) { yield return null; }

    if (request.isNetworkError || request.isHttpError)
    {
        Debug.Log(request.error);
        if (result != null)
            result(request.error);
    }
    else
    {
        Debug.Log(request.downloadHandler.data);
        if (result != null)
            result(request.downloadHandler.text);
    }
}

您可以使用lambda返回结果:

void NonCoroutineFunction()
{
    StartCoroutine(m_GetUserToken("YourURL", (v_UserToken) =>
    {
        //You can now use the v_UserToken variable
        Debug.Log(v_UserToken);
    }));
}