Сопрограммы Получить запрос - PullRequest
0 голосов
/ 06 февраля 2020

Я не могу понять, как правильно делать асинхронные запросы Get. У меня есть сопрограмма с запросом получения. Он возвращает мне идентификатор комнаты, который мне нужен, когда я записываю плеер, но проблема в том, что все это делается в одной функции, при создании комнаты, и из-за этого сопрограмма не успевает записать данные. Затем этот запрос Get используется в режиме реального времени для получения необходимых идентификаторов, которые меняются, и возникает та же проблема. Мой запрос Get:

    IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(Host + uri))
        {
            yield return webRequest.SendWebRequest();
            response = webRequest.downloadHandler.text;
        }
    }

Метод:

    public int GetID(string entity, string identify, string ID)
    {
        StartCoroutine(GetRequest(entity + identify));
        var json = ParseJson(response);
        return int.Parse(json[ID]);
    }

И где я его называю

    public void CreateRoom()
    {
        TypedLobby sqlLobby = new TypedLobby("myLobby", LobbyType.SqlLobby);
        string sqlLobbyFilter = "C0";
        SetNickName(userName.text);
        RoomOptions roomOptions = new RoomOptions
        {
            MaxPlayers = 5,
            CustomRoomProperties = new ExitGames.Client.Photon.Hashtable() { { sqlLobbyFilter, "0" } },
            CustomRoomPropertiesForLobby = new string[] { sqlLobbyFilter }
        };
        if (roomName.text.Length != 0)
        {
            client.PostRoom(roomName.text);
            var roomID =client.GetID("Rooms/", roomName.text, "IDRoom");
            client.PostPlayer(PhotonNetwork.NickName, roomID);
            PhotonNetwork.CreateRoom(roomName.text, roomOptions, sqlLobby);
        }
        else notice.EmptyRoomName();
    }

Ответы [ 2 ]

3 голосов
/ 06 февраля 2020

Похоже, вы пытаетесь линеаризовать сопрограмму. «StartCoroutine» не работает как ожидание.

Давайте сначала go о том, как работает ваша сопрограмма GetRequest.

IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(Host + uri))
        {
            yield return webRequest.SendWebRequest();
            response = webRequest.downloadHandler.text;
        }
    }

Приведенный выше код создает новый веб-запрос и возвращает элемент управления Unity каждый кадр до тех пор, пока веб-запрос завершен.

Думайте о yield return webRequest.SendWebRequest(); так:

while(!webRequest.isDone)
{
    //suspend the coroutine until next frame
    yield return null;
}

Это просто приостанавливает сопрограмму каждый кадр, пока не будет получен ответ.


Теперь давайте пройдемся по вашему коду и посмотрим, что происходит:

var roomID =client.GetID("Rooms/", roomName.text, "IDRoom");

, который вызывает:

public int GetID(string entity, string identify, string ID)
    {
        StartCoroutine(GetRequest(entity + identify));
        var json = ParseJson(response);
        return int.Parse(json[ID]);
    }

Начиная с webRequest.SendWebRequest () в вашем GetRequest метод не мгновенный, ответ не будет содержать анализируемые JSON данные, по крайней мере, до следующего кадра.

С GetID вызывается во фрейме (и не является сопрограммой), он выполняет все свои логики c в фрейме, который он вызывает. Он пытается Разобрать Json (ответ) на неустановленном ответе , поэтому ваша сопрограмма не успевает написать.


Как сделать мы это исправим?

К сожалению, универсального решения не существует. Вам нужно будет разграничить логику c, чтобы она могла происходить в нескольких кадрах. Умное использование Queues могло бы хорошо послужить здесь, или размещение большего количества логик c внутри CoRoutine также могло бы решить эту проблему.

Вот пример использования CoRoutines, так как Queues вероятно требуется больше кода для их мониторинга / обработки:

Переместите логи конфигурации комнаты c сопрограмму (и вместо того, чтобы вкладывать сопрограммы, просто вызовите веб-запрос из этого):

public IEnumerator ConfigureRoom(string roomNameText, RoomOptions roomOptions, TypedLobby sqlLobby)
    {
        client.PostRoom(roomNameText)
        using (UnityWebRequest webRequest = UnityWebRequest.Get("Rooms/" + roomNameText))
        {
            yield return webRequest.SendWebRequest();
            response = webRequest.downloadHandler.text;
        }
        var json = ParseJson(response);
        var roomId = int.Parse(json["IDRoom"]);
        client.PostPlayer(PhotonNetwork.NickName, roomID);
        PhotonNetwork.CreateRoom(roomNameText, roomOptions, sqlLobby);
    }
//Inside of your CreateRoom() method
        if (roomName.text.Length != 0)
        {
            StartCoroutine(ConfigureRoom(roomName.text, roomOptions, sqlLobby));
        }

Это позволяет создавать вашу комнату и обновлять данные в течение нескольких кадров.

Отказ от ответственности: Я набрал все это в браузере. Могут быть незначительные синтаксические ошибки. Пожалуйста, дайте мне знать, чтобы я мог их исправить.

2 голосов
/ 06 февраля 2020

Измените GetID на сопрограмму, дайте ему Action, чтобы использовать int, и используйте yield return GetRequest(...); вместо StartCoroutine(GetRequest(...));.

    IEnumerator GetRequest(string uri)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(Host + uri))
        {
            yield return webRequest.SendWebRequest();
            response = webRequest.downloadHandler.text;
        }
    }

метод:

    public IEnumerator GetID(string entity, string identify, string ID, Action<int> onComplete)
    {
        yield return GetRequest(entity + identify);
        var json = ParseJson(response);
        onComplete(int.Parse(json[ID]));
    }

И позвони ему

    public void CreateRoom()
    {
        TypedLobby sqlLobby = new TypedLobby("myLobby", LobbyType.SqlLobby);
        string sqlLobbyFilter = "C0";
        SetNickName(userName.text);
        RoomOptions roomOptions = new RoomOptions
        {
            MaxPlayers = 5,
            CustomRoomProperties = new ExitGames.Client.Photon.Hashtable() { { sqlLobbyFilter, "0" } },
            CustomRoomPropertiesForLobby = new string[] { sqlLobbyFilter }
        };
        if (roomName.text.Length != 0)
        {
            client.PostRoom(roomName.text);
            StartCoroutine(
                    client.GetID("Rooms/", roomName.text, "IDRoom", 
                        delegate(int roomID) { 
                            client.PostPlayer(PhotonNetwork.NickName, roomID);
                            PhotonNetwork.CreateRoom(roomName.text, roomOptions, sqlLobby);
                        }));
        }
        else notice.EmptyRoomName();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...