Android UnityWebRequest.SendWebRequest doens';不要用手机发送
我正在使用UnitywebRequest方法从HTTPS下载Assetbundles,但是UnitywebRequest.SendWebRequest似乎需要很长时间才能真正开始接收任何数据Android UnityWebRequest.SendWebRequest doens';不要用手机发送,android,unity3d,webrequest,assetbundle,Android,Unity3d,Webrequest,Assetbundle,我正在使用UnitywebRequest方法从HTTPS下载Assetbundles,但是UnitywebRequest.SendWebRequest似乎需要很长时间才能真正开始接收任何数据 public static IEnumerator DownloadMenuAssetBundle(string fileName) { string path = Path.Combine(Globals.Platform, fileName); UnityWebRequest www =
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
}
publicstaticienumerator下载menuassetbundle(字符串文件名)
{
字符串路径=path.Combine(Globals.Platform,文件名);
UnityWebRequest www=newUnityWebRequest(FileManager.RequestFile(path));//这将返回捆绑包的完整url,例如https://mywebsite.com/unity/myBundle
www.downloadHandler=new DownloadHandlerBuffer();
www.SendWebRequest();
而(!www.isDone)
{
Log(“响应:+www.responseCode”);
如果(www.isNetworkError)
{
Debug.Log(www.error);
}
Log(“下载:”+www.downloaddedbytes);
收益返回空;
}
Log(“下载字节:+www.downloaddedbytes”);
Log(“最终响应:+www.responseCode”);
如果(www.error!=null)
{
LogError(“下载时遇到错误:“+fileName+”:“+www.error”);
}
其他的
{
//其余的逻辑,这是可行的
}
Debug.Log(“响应:+www.downloadedBytes);
将返回0
一段随机时间(从几分钟到几分钟不等)。但是www.isNetworkError
不会被命中,一旦开始接收字节,它将在几毫秒内下载整个内容
以前,我在http服务器上使用了完全相同的脚本,它工作得完美无误,没有任何延迟,但一旦我切换到https,它开始需要一段时间。延迟也不会发生在编辑器中(Unity版本2017.2.1f1运行时版本.net 3.5,具有2.0子集api兼容性),而是发生在我的所有移动设备上(Oneplus 3、三星galaxy s8、三星galaxy s6)
起初www.responseCode
返回了一个永久移动的301
,我通过使用新的https url而不是http url解决了这个问题,希望这能解决它。但是它没有解决,现在我只得到200 OK
这也是一个不一致的问题,因为它所需要的时间并不总是一样的,它也不是一直都在发生(但大多数时候都是这样)
这是安全层花费额外时间还是服务器花费时间响应的问题?如果这是一个问题,我如何能够追踪到它(尽管我怀疑这一点,因为它在编辑器中工作得很好)
编辑:解决方法
我通过使用
WWW
类而不是UnityWebRequest
来解决这个问题。延迟现在完全消失了,但没有进行SSL证书验证,因为Unity似乎默认会拒绝它们。我不会真的称之为修复,但现在可以了。UnityWebRequest总是有问题,有时没有任何问题用统一的头脑来理解
你可以试着替换
UnityWebRequest www = new UnityWebRequest(FileManager.RequestFile(path));
与
测试可选:
另外,我认为您的while
循环不是“保存”以捕获网络错误。
我更喜欢下面提到的内容
希望这有帮助。您的
while
循环语句是错误的。您使用返回www.SendWebRequest()
同时使用while(!www.isDone)有什么意义
?通过产生SendWebRequest
while循环,现在使用while
循环是无针的,因为在执行while
循环之前,它将等待下载完成。使用while(!www.isDone)的想法
用于获取下载状态。此外,在这里使用yield return null
比WaitForSeconds(0.1f)
更好。为什么每0.1
秒检查或生成一次垃圾?是的,您使用无针while循环是正确的。但是如果yield return www.SendWebRequest();
正在等待下载完成,0.1秒的“垃圾”永远不会被处理。我有过这样的经验,即收益返回语句在移动和web上的行为很奇怪。我正在我的web项目中使用此代码。它正在工作。它不像协程应该如何工作那样“正确”。我还有另一个“等待协程”通过使用lambda:返回新的WaitUntil(()=>www.isDone
那么为什么要使用while
循环呢?注意OP是如何使用www.downloadedBytes
的,这意味着OP想并且必须使用而在这种情况下(!www.isDone)
返回新的WaitUntil()=>www.isDone也会产生垃圾,因为new waitill
和lambda与问题无关。我认为OP应该坚持yield return null
。你真的必须编辑你的答案。我第一次评论的主要原因不是关于优化,而是要指出你误用了www.isDone
属性,您仍然没有修复该属性。返回www.SendWebRequest();
将阻止请求,并且www.isDone
和www.downloadedBytes
将无法正常工作。我必须指出性能代码,因为您使用了一个不会生成垃圾的代码,并使它这样做,这实际上使它变得更糟,并且无法解决问题。我不是将您的代码称为“垃圾”或“无用代码”。我的意思是代码生成GC。请用谷歌搜索一下。不要太在意程序员在说什么,你会明白的。调用www.SendWebRequest()
然后在循环中等待UnityWebRequest.isDone
,而循环是可以的。但是,调用会返回www.SendWebRequest()
然后在循环中使用UnityWebRequest.isDone
等待,而循环则是不正常的。这是因为产生返回
将使它在SendWebRequest
中等待,直到请求完成。这使得isDone
的使用变得不正常
UnityWebRequest www = new UnityWebRequestAssetBundle(FileManager.RequestFile(path), 0);
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
}