OnMessage 中的 websocket-sharp 统一性问题

websocket-sharp unity problem in OnMessage

我正在制作游戏 在我的游戏大厅部分,使用网络套接字接收该房间的开场者列表 如果接收规范的时间间隔即使是2秒,工作也没有问题,但如果同时接收所有规范,MakeUILobby功能将无法使用!

    public IEnumerator Start()
    {
        ws = new WebSocket("ws://localhost:8081");
        ws.SetCookie();
        ws.Connect();
        WSConnectionStatus = true;
        ws.OnMessage += (sender, e) =>
        {
            WSUserJoinedToRoom = JsonUtility.FromJson<WSUserJoinedToRoom>(e.Data);
            print("Message Received from " + ((WebSocket)sender).Url + ", Data : " + e.Data);
            _actions.Enqueue(() => MakeUILobby(WSUserJoinedToRoom.user_id, WSUserJoinedToRoom.user_name));
        };
    }

    private void MakeUILobby(string user_id, string user_name)
    {
        print(user_name);
    }

WebSocket 数据第 1 部分:

{"user_id": "3", "user_name": "Player-3"}

WebSocket 数据第 2 部分:

{"user_id": "1", "user_name": "Player-1"}

但是如果你看上图,MakeUILobby 函数被调用了两次,其中包含玩家的信息,如果它应该像下图那样!

您的问题是value capturing in lambda expressions

字段 WSUserJoinedToRoom 的值在每次收到最后一个项目时都会更改,因此当主线程帧播放时,它将执行两个 lambda 操作,这两个操作都将访问相同的 WSUserJoinedToRoom 值。

所以在你的情况下

  • 玩家 3 被接收并存储到 WSUserJoinedToRoom 并且您添加回调操作
  • 玩家 1 被接收并存储到 WSUserJoinedToRoom 并且您添加回调操作
  • 现在主线程执行更新并执行从 current WSUserJoinedToRoom(玩家1), 不是 回调 Enqueued!
  • 时的回调

而是将两个字符串存储在局部变量之前:

ws.OnMessage += (sender, e) =>
{
    WSUserJoinedToRoom = JsonUtility.FromJson<WSUserJoinedToRoom>(e.Data);
    print("Message Received from " + ((WebSocket)sender).Url + ", Data : " + e.Data);
    // HERE: Store new variables for the values
    var userId = WSUserJoinedToRoom.user_id;
    var userName = WSUserJoinedToRoom.user_name;
    _actions.Enqueue(() => MakeUILobby(userId, userName));
};

或者根本不使用 WSUserJoinedToRoom 的字段,而是

ws.OnMessage += (sender, e) =>
{
    // HERE: Simply make a new variable everytime
    var WSUserJoinedToRoom = JsonUtility.FromJson<WSUserJoinedToRoom>(e.Data);
    print("Message Received from " + ((WebSocket)sender).Url + ", Data : " + e.Data);
    _actions.Enqueue(() => MakeUILobby(WSUserJoinedToRoom.user_id, WSUserJoinedToRoom.user_name));
};