【问题标题】:UnityWebRequest.SendWebRequest doens't send on mobileUnityWebRequest.SendWebRequest 不在移动设备上发送
【发布时间】:2018-10-01 09:39:54
【问题描述】:

我正在使用来自 HTTPS 的 UnitywebRequest 方法下载 Assetbundles,但是 UnityWebRequest.SendWebRequest 似乎花了不少时间才能真正开始接收任何数据。

public static IEnumerator DownloadMenuAssetBundle(string fileName)
{
    string path = Path.Combine(Globals.Platform, fileName);
    UnityWebRequest www = new UnityWebRequest(FileManager.RequestFile(path));//this returns the complete url to the bundle e.g https://mywebsite.com/unity/myBundle
    www.downloadHandler = new DownloadHandlerBuffer();
    www.SendWebRequest();
    while (!www.isDone)
    {
        Debug.Log("response: " + www.responseCode);
        if (www.isNetworkError)
        {
            Debug.Log(www.error);
        }
        Debug.Log("downloaded:" + www.downloadedBytes);
        yield return null;
    }
    Debug.Log("downloaded bytes: " + www.downloadedBytes);
    Debug.Log("final response:" + www.responseCode);

    if (www.error != null)
    {
        Debug.LogError("Encountered error while downloading: <color=blue>" + fileName + "</color>: " + www.error);
    }
    else
    {
       //rest of the logic, this works
    } 

Debug.Log("response: " + www.downloadedBytes); 将在随机的时间内返回0(有时从几分钟到几分钟不等)。但是www. isNetworkError 永远不会被命中,一旦开始接收字节,它将在几毫秒内下载整个内容。

以前我在 http 服务器上使用完全相同的脚本,它运行完美,没有任何延迟,但是一旦我切换到 https,它开始需要一段时间。延迟也不会发生在编辑器中(Unity 版本 2017.2.1f1 运行时版本 .net 3.5,具有 2.0 子集 api 兼容性),但会发生在我所有的移动设备(一加 3、三星 Galaxy s8、三星 Galaxy s6)上。

起初www.responseCode 返回了301 Moved Permanently,我通过使用新的 https url 而不是 http url 解决了这个问题,希望这能解决它。然而它没有,现在我只得到200 OK

这也是一个不一致的问题,因为它所花费的时间并不相同,甚至也不会一直发生(但大部分时间都会发生)

这可能是安全层花费额外时间或服务器花费时间响应的问题吗?如果这是问题所在,我将如何追踪它(尽管我对此表示怀疑,因为它在编辑器中运行良好)?

编辑:解决方法 我通过使用WWW 类而不是UnityWebRequest 解决了这个问题。延迟现在完全消失了,但没有进行 SSL 证书验证,因为 Unity 似乎默认拒绝它们。我不会真正称其为修复程序,但现在可以使用。

【问题讨论】:

  • while 循环中删除if (www.isNetworkError)。您应该只在循环完成后和循环之外执行此操作。如果出现错误,循环应该立即退出。
  • 我刚看到你的编辑。您是否有要在请求期间验证的 SSL 证书?
  • @Programmer 是的,如果可能的话。我不得不说,到目前为止,我还没有时间彻底调查/调查它。但假设我必须使用 x509 创建证书存储?
  • 我怀疑。请注意完全确定,但您可以使用UnityWebRequest.certificateHandler 看看会发生什么。 This 显示如何验证证书。您还可以查看我的other,这也是使用WebRequest 在Android 上减慢UnityWebRequest 的解决方案
  • 您好,您能告诉我如何使用 www 类发送 post 请求吗?现在找不到任何过时的文档

标签: android unity3d webrequest assetbundle


【解决方案1】:

UnityWebRequest 总是有问题 - 有时 UnityWebRequests 没有任何意义...

你可以尝试替换

 UnityWebRequest www = new UnityWebRequest(FileManager.RequestFile(path));

 UnityWebRequest www = new UnityWebRequestAssetBundle(FileManager.RequestFile(path), 0);

测试可选:

我还认为您的while 循环不是“保存”来捕获网络错误。 我更喜欢documentation中提到的以下内容@

UnityWebRequest www = new UnityWebRequestAssetBundle(FileManager.RequestFile(path);
yield return www.SendWebRequest();

if (request.isNetworkError || request.isHttpError)
{
    Debug.Log(www.error.ToString());
}
else
{
    // for testing only // if yield return www.SendWebRequest(); is working as expected www.isDone = true here!
    while (!www.isDone)
    {
        Debug.Log("Something is wrong! "  + www.responseCode);
        yield return new WaitForSeconds(0.1f);
    }
    // do whatever you want
}

希望这会有所帮助。

【讨论】:

  • 您的while 循环语句是错误的。你在使用yield return www.SendWebRequest() 的同时还使用while (!www.isDone) 有什么意义?通过产生SendWebRequestwhile 循环的使用现在是无限制的,因为它会等到下载完成后再执行while 循环。使用while (!www.isDone) 的想法是获取下载状态。此外,在这里使用yield return null 比使用WaitForSeconds(0.1f) 更好。为什么要每隔0.1 秒检查或生成垃圾?
  • 是的,您对无品位的 while 循环是正确的。但是,如果yield return www.SendWebRequest(); 正在等待下载完成,则永远不会处理 0.1 秒的“垃圾”。我的经验是,yield return 语句在移动设备和网络上表现得很奇怪。我正在我的网络项目中使用此代码。它正在工作。协程应该如何工作并不“正确”。我有另一个使用 lambda 的“等待协程”:yield return new WaitUntil(() =&gt; www.isDone
  • 那么为什么会有while 循环呢?请注意 OP 如何使用 www.downloadedBytes,因此这意味着 OP 在这种情况下想要并且必须使用 while (!www.isDone)。同样,由于new WaitUntil 和 lambda,yield return new WaitUntil(() =&gt; www.isDone 也会产生垃圾,它们与问题无关。我认为 OP 应该坚持使用yield return null。你真的必须编辑你的答案。
  • 我第一个评论的主要原因是不是关于优化,而是指出您滥用了您仍未修复的www.isDone 属性。 yield return www.SendWebRequest();阻止请求,www.isDonewww.downloadedBytes 将无法正常工作。我不得不指出性能代码,因为您采用了一个不会产生垃圾的代码并让它这样做,这实际上使它变得更糟并且没有解决问题。我称您的代码为“垃圾”或“无用代码”。我的意思是代码会生成 GC。拜托,谷歌一下。
  • 稍微注意一下程序员在说什么,你就会明白的。调用www.SendWebRequest() 然后在while 循环中等待UnityWebRequest.isDone 是可以的。但是,调用yield return www.SendWebRequest() 然后在while 循环中等待UnityWebRequest.isDone 是不行的。这是因为yield return 将使它在SendWebRequest 中等待,直到请求完成。这使得isDone 的使用变得多余,并且无法使用www.downloadedBytes,因为请求在到达www.downloadedBytes 所在的位置时就已经完成了。
猜你喜欢
  • 1970-01-01
  • 2016-01-27
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多