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

Unity3D与Python Websocket通信稳定性问题咨询

Unity3D 与 Python Websockets 通信实现指南

我看你正在搭建Unity3D应用和Python的websockets通信链路,从你给出的代码片段来看,应该是结合了OPC数据采集的场景对吧?下面我帮你补全整个通信流程,从Python端的完善到Unity端的实现,还有实用的调试技巧。

一、Python端代码完善(结合OPC数据推送)

你给出的SubHandler是OPC数据变更的回调类,我们可以把它和websocket服务结合,实现OPC数据实时推送到Unity。以下是完整的Python示例代码:

from __future__ import division
import asyncio
import websockets
import time
import os
import json
from threading import Thread
from random import randint
from read import CustOPCLib
import socket
from jsonsocket import Client,Server

# OPC数据处理类:接收OPC数据变更并推送到Unity
class SubHandler(object):
    def __init__(self, websocket):
        self.websocket = websocket  # 关联当前websocket连接
    
    def data_change(self, handle, node, val, attr):
        print(f"Python: 检测到OPC数据变更 -> 节点: {node}, 值: {val}")
        # 将数据序列化为JSON格式(推荐,方便Unity解析)
        data = json.dumps({
            "node": node,
            "value": val,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        })
        # 异步发送数据到Unity
        asyncio.run(self.send_to_unity(data))
    
    async def send_to_unity(self, data):
        try:
            await self.websocket.send(data)
            print(f"Python: 已推送数据到Unity: {data}")
        except websockets.exceptions.ConnectionClosed:
            print("Python: 与Unity的连接已断开")

# Websocket服务端核心逻辑
async def unity_websocket_handler(websocket, path):
    print("Python: Unity客户端已连接")
    # 初始化OPC处理器并绑定当前websocket连接
    opc_handler = SubHandler(websocket)
    
    # 初始化OPC客户端并订阅节点(根据你的CustOPCLib实际逻辑调整)
    cust_opc = CustOPCLib(sub_handler=opc_handler)
    cust_opc.connect_to_server()  # 连接OPC服务器
    cust_opc.subscribe_target_nodes()  # 订阅需要监控的OPC节点
    
    try:
        # 监听Unity发送的指令
        async for message in websocket:
            print(f"Python: 收到Unity消息: {message}")
            # 根据指令执行对应操作,比如主动请求某节点数据
            if message == "request_opc_status":
                status_data = json.dumps({"status": "connected", "node_count": cust_opc.get_subscribed_node_count()})
                await websocket.send(status_data)
    finally:
        print("Python: Unity客户端已断开连接")
        # 清理OPC资源
        cust_opc.unsubscribe_nodes()
        cust_opc.disconnect_from_server()

# 启动Websocket服务(单独线程避免阻塞)
def start_websocket_service():
    server = websockets.serve(unity_websocket_handler, "0.0.0.0", 8765)
    asyncio.get_event_loop().run_until_complete(server)
    asyncio.get_event_loop().run_forever()

if __name__ == "__main__":
    # 启动websocket服务线程
    ws_thread = Thread(target=start_websocket_service, daemon=True)
    ws_thread.start()
    
    # 保持主进程运行
    while True:
        time.sleep(5)

代码关键点说明

  • 给SubHandler增加了websocket连接关联,让OPC数据变更时能直接推送到Unity
  • 使用JSON格式传输数据,避免解析混乱,Python端用json.dumps()序列化
  • 用线程启动websocket服务,防止OPC的阻塞操作影响通信
  • 增加了Unity指令监听逻辑,可以实现双向通信

二、Unity端WebSocket客户端实现

Unity端我们用WebSocketSharp库来实现websocket通信(比Unity自带的API更易用),以下是C#示例代码:

using UnityEngine;
using WebSocketSharp;
using System;

public class UnityWebSocketClient : MonoBehaviour
{
    [Header("WebSocket配置")]
    [SerializeField] private string serverUrl = "ws://localhost:8765";
    private WebSocket ws;

    void Start()
    {
        InitializeWebSocket();
    }

    // 初始化WebSocket连接
    void InitializeWebSocket()
    {
        ws = new WebSocket(serverUrl);
        
        // 连接成功回调
        ws.OnOpen += (sender, e) =>
        {
            Debug.Log("<color=green>Unity: 已连接到Python服务器</color>");
            // 发送初始化指令给Python
            SendMessageToPython("unity_connected");
        };
        
        // 接收消息回调
        ws.OnMessage += (sender, e) =>
        {
            Debug.Log($"Unity: 收到Python数据 -> {e.Data}");
            // 解析JSON数据(需要对应的数据模型)
            ProcessReceivedOPCData(e.Data);
        };
        
        // 连接断开回调
        ws.OnClose += (sender, e) =>
        {
            Debug.LogWarning($"Unity: 与Python服务器断开连接,原因: {e.Reason}");
            // 5秒后尝试重连
            Invoke(nameof(TryReconnect), 5f);
        };
        
        // 错误回调
        ws.OnError += (sender, e) =>
        {
            Debug.LogError($"Unity: WebSocket错误 -> {e.Message}");
        };
        
        // 开始连接
        ws.Connect();
    }

    // 解析收到的OPC数据
    void ProcessReceivedOPCData(string jsonData)
    {
        // 反序列化为数据模型
        OPCDataModel opcData = JsonUtility.FromJson<OPCDataModel>(jsonData);
        if(opcData != null)
        {
            Debug.Log($"解析后数据: 节点={opcData.node}, 值={opcData.value}, 时间={opcData.timestamp}");
            // 这里可以更新UI、游戏逻辑等
        }
    }

    // 发送消息到Python
    public void SendMessageToPython(string message)
    {
        if(ws != null && ws.IsAlive)
        {
            ws.Send(message);
            Debug.Log($"Unity: 发送消息到Python -> {message}");
        }
        else
        {
            Debug.LogWarning("Unity: WebSocket未连接,无法发送消息");
        }
    }

    // 尝试重连
    void TryReconnect()
    {
        if(!ws.IsAlive)
        {
            ws.Connect();
            Debug.Log("Unity: 尝试重连Python服务器...");
        }
    }

    // 销毁时关闭连接
    void OnDestroy()
    {
        if(ws != null && ws.IsAlive)
        {
            ws.Close(CloseStatusCode.Normal, "Unity客户端退出");
        }
    }
}

// OPC数据模型(与Python端对应)
[Serializable]
public class OPCDataModel
{
    public string node;
    public float value;
    public string timestamp;
}

Unity端注意事项

  • 导入WebSocketSharp:可以通过NuGet下载,或者直接导入对应的dll文件到Unity的Plugins文件夹
  • 数据模型要和Python端的JSON结构完全对应,否则无法正常解析
  • 增加了自动重连逻辑,提升通信稳定性
  • 建议在OnDestroy中关闭连接,避免资源泄漏

三、调试与优化技巧

  • 本地测试:确保Python和Unity在同一机器,用localhost:8765测试,没问题再切换到局域网IP
  • 日志打印:两端都要打印详细日志,方便定位连接失败、数据解析错误等问题
  • 异常捕获:在Python的websocket发送、Unity的数据解析处增加异常捕获,避免程序崩溃
  • 心跳机制:可以定期发送心跳包,检测连接是否正常,比如每10秒发送一次ping消息

内容的提问来源于stack exchange,提问作者hoek rand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:09:21