UnityWebRequest.SendWebRequest не отправляется на мобильный

Я загружаю Assetbundles, используя метод UnitywebRequest из HTTPS, однако 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 с совместимостью с подмножеством API 2.0), но происходит на всех моих мобильных устройствах (Oneplus 3, samsung galaxy s8, samsung galaxy s6).

Сначала www.responseCode вернул 301 Moved Permanently, я решил это, используя новый URL-адрес https вместо URL-адреса http, надеясь, что это исправит это. Однако этого не произошло, и теперь я получаю только 200 OK.

Это также непоследовательная проблема, потому что время, которое требуется, никогда не бывает одинаковым, и это даже не происходит все время (но происходит в большинстве случаев).

Может ли это быть проблемой из-за того, что уровню безопасности требуется дополнительное время, или серверу требуется время для ответа? если это проблема, как я могу отследить это (хотя я сомневаюсь, что это хорошо работает в редакторе)?

РЕДАКТИРОВАТЬ: обходной путь Я решил проблему, используя класс WWW вместо UnityWebRequest. задержка полностью исчезла, но проверка SSL-сертификата не выполняется, поскольку Unity, похоже, отклоняет их по умолчанию. Я бы не назвал это исправлением, но пока работает.


person Remy    schedule 01.10.2018    source источник
comment
Удалите if (www.isNetworkError) из цикла while. Вы должны делать это только после завершения цикла и вне его. Если есть ошибка, цикл должен выйти сразу.   -  person Programmer    schedule 01.10.2018
comment
Я только что увидел твою правку. У вас есть SSL-сертификат, который вы хотите проверить во время запроса?   -  person Programmer    schedule 05.10.2018
comment
@Программист да, если возможно. Я должен сказать, что до сих пор у меня еще не было времени, чтобы исследовать/изучать его полностью. Но предположим, мне нужно создать хранилище сертификатов с использованием x509?   -  person Remy    schedule 05.10.2018
comment
Я подозреваю, что. Обратите внимание, конечно, но вы можете использовать UnityWebRequest.certificateHandler и посмотреть, что произойдет. Это показывает, как проверить сертификат. Вы также можете проверить мой другой, который также является решением для замедления UnityWebRequest на Android с помощью WebRequest   -  person Programmer    schedule 06.10.2018
comment
Привет, не могли бы вы показать мне, как использовать класс www для отправки почтового запроса? не могу найти документацию о том, что она устарела   -  person Jerin Cherian    schedule 06.02.2020


Ответы (1)


Всегда проблемы с UnityWebRequest - иногда с UnityWebRequests ничего не понятно...

можно попробовать заменить

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

с

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

Необязательно для тестирования:

Также я думаю, что ваш цикл while не «сохраняется», чтобы поймать сетевую ошибку. Я бы предпочел следующее, как указано в документации

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
}

Надеюсь это поможет.

person dome12b    schedule 01.10.2018
comment
Ваше утверждение цикла while ложно. Какой смысл использовать yield return www.SendWebRequest(), а также использовать while (!www.isDone)? При выдаче SendWebRequest использование цикла while теперь бесконтактно, поскольку он будет ждать, пока загрузка не будет выполнена, прежде чем цикл while получит выполнение. Идея использования while (!www.isDone) состоит в том, чтобы получить статус загрузки. Кроме того, здесь лучше использовать yield return null, чем WaitForSeconds(0.1f). Зачем проверять или генерировать мусор каждые 0.1 секунд? - person Programmer; 01.10.2018
comment
Да, вы правы с бесконтактным циклом while. Но если yield return www.SendWebRequest(); ждет завершения загрузки, мусор 0,1 секунды никогда не обрабатывается. У меня есть опыт, когда операторы yield return ведут себя странно на мобильных устройствах и в Интернете. Я работаю с этим кодом в своем веб-проекте. И это работает. Это неправильно, как должны работать сопрограммы. У меня есть еще одна ожидающая сопрограмма с использованием лямбда: yield return new WaitUntil(() => www.isDone - person dome12b; 01.10.2018
comment
Тогда зачем вообще нужен цикл while? Обратите внимание, как OP использует www.downloadedBytes, так что это означает, что OP хочет и должен использовать while (!www.isDone) в этом случае. Опять же, yield return new WaitUntil(() => www.isDone также генерирует мусор из-за new WaitUntil и лямбда, и они не имеют ничего общего с проблемой. Я думаю, что ОП должен придерживаться yield return null. Вам действительно нужно отредактировать свой ответ. - person Programmer; 01.10.2018
comment
Я думаю, что мы ищем решение, а не оптимизацию. Мусор в плане бесполезного кода тут не при чем. И опять же, если запрос работает, нет необходимости в дополнительном цикле WaitUntil или while — я знаю. Мой подход заключается в использовании UnityWebRequestAssetBundle как есть. сделаю правку ;) - person dome12b; 01.10.2018
comment
Основная причина моего первого комментария заключалась не в оптимизации, а в том, чтобы указать вам, что вы неправильно использовали свойство www.isDone, которое вы до сих пор не исправили. yield return www.SendWebRequest(); заблокирует запрос, а www.isDone и www.downloadedBytes не будут работать должным образом. Мне пришлось указать на код производительности, потому что вы взяли код, который не генерирует мусор, и заставили его делать это, что на самом деле сделало его хуже и не решило проблему. Я не называю ваш код Мусором или бесполезным кодом. Я имел в виду, что код генерирует GC. Пожалуйста, погуглите это. - person Programmer; 01.10.2018
comment
Вау... www.isDone не работает должным образом после yield return www.SendWebRequest(); ?! Я думаю, вам стоит погуглить UnityWebRequest.isDone... Я не ошибся в вашей фигне - но все же думаю, что здесь не в этом дело. Но, пожалуйста, покажите нам свое решение и проголосуйте за мой ответ. Просто хотел показать OP (ложное) решение, работающее в моем случае. не звоните www.downloadedBytes через Интернет или мобильный телефон. Корутины на самом деле не работают асинхронно. Между делом работают. Это тоже можно погуглить... - person dome12b; 01.10.2018
comment
Не обращайте внимания на то, что говорит программист, и вы его поймете. Вызов www.SendWebRequest(), а затем ожидание с UnityWebRequest.isDone в цикле while — это нормально. Однако вызов yield return www.SendWebRequest(), а затем ожидание с UnityWebRequest.isDone в цикле while НЕ ОК. Это связано с тем, что yield return заставит его ждать в SendWebRequest, пока запрос не будет выполнен. Это делает использование isDone избыточным, а www.downloadedBytes нельзя использовать, потому что запрос будет завершен к тому времени, когда он достигнет места, где находится www.downloadedBytes. - person PassetCronUs; 01.10.2018
comment
Идея использования www.downloadedBytes состоит в том, чтобы получить статус/прогресс загрузки, в то время как данные все еще загружаются, и это должно использоваться с isDone правильно. Если вам не нужна эта информация, просто используйте yield return www.SendWebRequest(). Обратите внимание, как OP использовал www.downloadedBytes. Это признак того, что он хочет этого. - person PassetCronUs; 01.10.2018
comment
к сожалению, UnityWebRequestAssetBundle не реализовано до Unity 2018 (у меня 2017.1f1), а его устаревшая версия UnityWebRequest.GetAssetbundle не решает эту проблему. Вы и Программист правы в том, что моя проверка networkError находится в неправильном месте, поэтому исправлено. Теперь я попытался загрузить пакеты, используя вместо этого класс WWW, и это, похоже, устранило задержку. - person Remy; 03.10.2018
comment
чтобы уточнить, в коде, который я разместил выше, я действительно использую while(!www.isDone) только для чтения хода загрузки, так как я хотел знать, действительно ли он загружался очень медленно (возможно, плохой интернет или что-то еще) или он не начался в все. для готового кода я поменяю на yield return www.SendWebRequest() - person Remy; 03.10.2018