协程获取请求

时间:2020-02-05 21:00:24

标签: c# unity3d

我不知道如何正确发出异步Get请求。我有要求的协程。它返回给我录制播放器时所需的房间ID,但问题是所有这些操作都是在一个函数中完成的,在创建房间时,因此,协程没有时间写入数据。然后,此Get请求被实时使用,以获取更改的必要ID,并且存在相同的问题。 我的获取请求:

    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 个答案:

答案 0 :(得分:3)

您似乎正在尝试线性化协程。 “ StartCoroutine”的功能不像等待。

让我们首先探讨一下GetRequest协程的工作原理。

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

上面的代码创建一个新的Web请求,并将控制权每帧返回给Unity 直到该Web请求完成。

像这样思考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]);
    }

由于您的 GetRequest 方法中的 webRequest.SendWebRequest()不是即时的,因此至少在下一个响应中,响应将不包含可解析的JSON数据。框架。

由于在框架上调用了 GetID (它本身不是协程),因此它在被调用的框架中执行所有逻辑。它尝试对未设置的响应进行 ParseJson(response),这就是您的协程没有时间写的原因。


我们如何解决这个问题?

不幸的是,还没有一种万能的解决方案。您需要使逻辑去线性化,以便它可以出现在多个帧中。巧妙地使用 Queue 可以在这里很好地工作,或者在CoRoutine中添加更多逻辑也可以解决它。

这是使用CoRoutines的示例,因为队列可能需要更多代码来监视/处理它们:

将您的房间配置逻辑移动到一个协程中(而不是嵌套协程,只需在此内调用webrequest即可):

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));
        }

这允许您在多个帧的过程中创建房间并更新数据。

免责声明:我已经在浏览器中输入了所有这些信息。可能存在较小的语法错误。请让我知道,以便我纠正它们。

答案 1 :(得分:2)

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();
    }