Unity中通过WebSocket实时发送GameObject位置至面板失败求助
问题分析与解决方案
核心问题在于:WebSocketBehavior 确实无法继承 MonoBehaviour,且直接在其中编写死循环会阻塞WebSocket的工作线程,同时Unity的主线程与WebSocket线程相互独立,无法直接通过Behavior内的循环触发实时数据推送。以下是具体解决思路和代码实现:
解决思路
- 拆分职责:将WebSocket服务器的生命周期管理、连接维护放在单例MonoBehaviour脚本中,利用Unity的帧更新(Update)机制触发数据发送;WebSocketBehavior仅负责处理连接、断开等会话事件。
- 会话管理:在MonoBehaviour中维护已连接的WebSocket会话列表,通过Unity的Update每帧遍历列表,主动推送位置数据。
- 线程安全:避免在WebSocket线程中直接操作Unity GameObject,所有与Unity对象相关的操作都放在主线程的Update中执行。
示例代码实现
1. WebSocket服务器管理器(MonoBehaviour单例)
using UnityEngine; using WebSocketSharp; using WebSocketSharp.Server; using System.Collections.Generic; public class WebSocketLocationServer : MonoBehaviour { public static WebSocketLocationServer Instance; private WebSocketServer _server; private List<WebSocketSession> _connectedSessions = new List<WebSocketSession>(); public Transform targetObject; // 拖拽需要追踪的GameObject Transform到这里 private void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); // 启动WebSocket服务 _server = new WebSocketServer("ws://localhost:8080"); _server.AddWebSocketService<LocationSession>("/location"); _server.Start(); } private void Update() { if (targetObject == null || _connectedSessions.Count == 0) return; // 序列化位置数据(这里用简易JSON格式,也可改用Newtonsoft.Json等库) string locationJson = $"{{\"x\":{targetObject.position.x:F2},\"y\":{targetObject.position.y:F2},\"z\":{targetObject.position.z:F2}}}"; // 遍历会话发送数据,用ToArray避免遍历中修改列表引发异常 foreach (var session in _connectedSessions.ToArray()) { if (session.Context.WebSocket.ReadyState == WebSocketState.Open) session.Send(locationJson); else _connectedSessions.Remove(session); } } private void OnDestroy() { _server?.Stop(); } // 供WebSocket会话调用的添加/移除方法 public void AddConnectedSession(WebSocketSession session) { if (!_connectedSessions.Contains(session)) _connectedSessions.Add(session); } public void RemoveConnectedSession(WebSocketSession session) { if (_connectedSessions.Contains(session)) _connectedSessions.Remove(session); } }
2. WebSocket会话处理类(WebSocketBehavior)
using WebSocketSharp.Server; public class LocationSession : WebSocketBehavior { protected override void OnOpen() { WebSocketLocationServer.Instance.AddConnectedSession(this); } protected override void OnClose(CloseEventArgs e) { WebSocketLocationServer.Instance.RemoveConnectedSession(this); } }
注意事项
- 不要在WebSocketBehavior内编写无限循环,会直接阻塞WebSocket工作线程,导致连接事件无法响应。
- 发送数据时尽量使用轻量化的序列化格式,避免频繁发送大体积数据影响性能。
- 确保前端面板的连接地址与Unity服务器地址(
ws://localhost:8080/location)完全一致,端口无冲突。
内容的提问来源于stack exchange,提问作者Jan Arend
相关产品推荐
相关产品推荐

