首页 > 解决方案 > OnMessage 中的 websocket-sharp 统一问题

问题描述

我正在制作游戏 在我的游戏大厅部分,使用 web socket 接收该房间的开启者列表 如果接收规范之间的时间间隔为 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 函数被调用了两次,带有玩家的信息,如果它应该像下面的图片一样!

在此处输入图像描述

标签: c#unity3dwebsocket

解决方案


您的问题是lambda 表达式中的值捕获

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

所以在你的情况下

  • 播放器 3 被接收并存储到WSUserJoinedToRoom您添加回调操作
  • 播放器 1 被接收并存储到WSUserJoinedToRoom您添加回调操作
  • 现在主线程执行更新并执行从当前(玩家 1)读取user_id和的两个动作,而不是回调d 时的动作!user_name WSUserJoinedToRoomEnqueue

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

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

推荐阅读