我对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仍然为空。
答案 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);
}));
}