You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity使用websocket-sharp时OnMessage并发消息导致MakeUILobby参数异常

问题根因

这是C# 闭包变量捕获的典型问题,叠加了WebSocket异步回调和Unity主线程调度的特性:

  1. 你声明的WSUserJoinedToRoom是类级别的全局变量,每次WebSocket收到消息都会直接覆盖这个变量的存储值
  2. 你入队的Lambda表达式捕获的是WSUserJoinedToRoom这个变量的引用,不是当前收到消息时的瞬时值
  3. 短时间内多条消息到达时,前一条消息的Lambda还没被执行,WSUserJoinedToRoom就已经被后一条消息的解析结果覆盖,最终所有Lambda执行时读取的都是最后一次覆盖的值

修复方案

把解析结果存在WebSocket回调的局部变量中,让Lambda捕获每次独立的局部变量副本即可,修改后的代码如下:

public IEnumerator Start()
{
    ws = new WebSocket("ws://localhost:8081");
    ws.SetCookie();
    ws.Connect();
    WSConnectionStatus = true;
    ws.OnMessage += (sender, e) =>
    {
        // 解析结果存入当前回调的局部变量,不要用全局变量中转
        var currentUser = JsonUtility.FromJson<WSUserJoinedToRoom>(e.Data);
        print("Message Received from " + ((WebSocket)sender).Url + ", Data : " + e.Data);
        // Lambda捕获当前回调的独立局部变量,不会被后续回调覆盖
        _actions.Enqueue(() => MakeUILobby(currentUser.user_id, currentUser.user_name));
    };
}

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

// 额外补充:你需要在Unity主线程生命周期函数中消费队列,否则入队的方法不会执行
private void Update()
{
    while (_actions.Count > 0)
    {
        _actions.Dequeue()?.Invoke();
    }
}

修改后原来的类级别WSUserJoinedToRoom变量如果没有其他用途可以直接删除,避免后续再出现类似的变量覆盖问题。

内容的提问来源于stack exchange,提问作者Mohammad Nikouei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 20:45:08