Python与Unity之间通信实现【Socket实现】

最近做的项目需要实现Python与Unity之间的数据通信,Unity中也有python的插件如IronPython、PyUnity,但是我的python环境和模型都在WSL2中配置了,就选择了用Socket通信的方法实现。
 

一、Python实现连接和传输

思路就是把一个np二维/一维数组转换为list类型,然后两两数字之间插入","作为分割转换为字符串类型,转换为UTF-8编码的字节流,通过socket发送。

python部分的实现:

import numpy as np
import socket
import os

def connect_unity(host,port):
    global sock
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # sock = socket.socket()
    sock.connect((host, port))
    print('连接已建立')

def send_to_unity(arr):
    arr_list = arr.flatten().tolist() # numpy数组转换为list类型
    data = '' + ','.join([str(elem) for elem in arr_list]) + ''  # 每个float用,分割
    sock.sendall(bytes(data, encoding="utf-8"))  # 发送数据
    print("向unity发送:", arr_list)

def rec_from_unity():
    data = sock.recv(1024)
    data = str(data, encoding='utf-8')
    data = data.split(',')
    new_data = []
    for d in data:
        new_data.append(float(d))
    print('从环境接收:',new_data)
    return new_data

# 生成随机数据
data = np.random.random(731,71)

host = '127.0.0.1'
port = 5005   

connect_unity(host,port)

for i in range(output_data.shape[0]):
    send_to_unity(output_data[i])
    rec_from_unity()  # Unity接收数据后再发送下一个

二、Unity实现监听和传输

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
public class U2P
{
    private static U2P instance;
    private Socket serverSocket;
    private Socket clientSocket;
    public bool isConnected;

    public static U2P Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new U2P();
            }
            return instance;
        }
    }
    private U2P()
    {
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
        // IPAddress ipAddress = IPAddress.Parse("0.0.0.0");
        serverSocket.Bind(new IPEndPoint(ipAddress, 5005));  
        serverSocket.Listen(5); 
        StartServer();
    }
    private void StartServer()
    {
        serverSocket.BeginAccept(AcceptCallback, null);
    }
    private void AcceptCallback(IAsyncResult ar)
    {
        Socket sc = serverSocket.EndAccept(ar); 
        if (clientSocket == null)
        {
            clientSocket = sc; 
            isConnected = true;
            Debug.Log("连接成功");
        }
    }
    public float[] RecData()
    {
        try
        {
            if (clientSocket != null)
            {
                int canRead = clientSocket.Available;
                byte[] buff = new byte[canRead];
                clientSocket.Receive(buff);
                string str = Encoding.UTF8.GetString(buff);
                //Debug.Log(str);
                if (str == "")
                {
                    return null;
                }
                //str = str.Replace("[","").Replace("]","").Replace("\n")Replace("Replace(
                //Debug.Log(“接受消息:”+ str);
                string[] strData = str.Split(',');
                float[] data = new float[strData.Length];
                for (int i = 0; i < strData.Length; i++)
                {
                    data[i] = float.Parse(strData[i]);
                }
                return data;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError("发生错误:"+ex);
            if (clientSocket != null)
            {
                clientSocket.Close(); 
                clientSocket = null; 
                isConnected = false;
                StartServer();
            }
        }
        return null;
    }
    public void SendData(List<float> data)
    {
        try
        {
            if (clientSocket != null)
            {
                string strData = "";
                for (int i = 0; i < data.Count; i++)
                {
                    strData += data[i];
                    if (i != data.Count - 1)
                    {
                        strData += ",";
                    }
                }
                // 使用clientSocket发送strData到服务器的代码
                byte[] dataBytes = Encoding.UTF8.GetBytes(strData);
                clientSocket.Send(dataBytes);
            }
        }
        catch (Exception ex)
        {
            //Debug.LogError("发生错误:”+ex);
            if (clientSocket != null)
            {
                clientSocket.Close();
                clientSocket = null;
                isConnected = false;
                StartServer();
            }
        }
    }
}

调用上述U2P类的代码,挂在到场景中的一个物体中:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Animations;
using UnityEditor;

public class Connect : MonoBehaviour
{
    private void Update()
    {
        if (U2P.Instance.isConnected)
        {
            float[] data = U2P.Instance.RecData();
            if (data != null)
            {
                print(data.Length);
                print("接收到数据");
                U2P.Instance.SendData(new List<float>(){0}); // 返回0,表示接收到数据
                // TODO: 处理数据
            }
        }
    }
}

需要注意的是,由于这种方法是将float类型(4字节)转换为字符串类型,因此一个浮点数如果是10长度,则需要10个字节,但是socket的单次传输是有限制的,如果需要传输很大数据,所以这里使用分多次连续传输,以一次接受到返回0为接受成功。

  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
nodeeditor是一个基于Qt的节点编辑器,用于数据流编程框架。它提供了一个可视化的界面,让用户可以通过连接不同的节点来构建数据流图。每个节点代表一个特定的功能或操作,而连接则表示数据的流动。 在nodeeditor中,用户可以创建自定义的节点,并定义节点之间的连接规则。每个节点可以有输入和输出端口,用于接收和发送数据。用户可以通过拖拽和连接不同的节点来构建数据流图,并通过节点之间的连接来传递数据。 nodeeditor还提供了一些常用的连接风格类,如ConnectionStyle,用于定义节点之间连接的样式和外观。用户可以根据自己的需求自定义连接的样式,以使数据流图更加直观和易于理解。 以下是一个简单的示例,演示了如何使用nodeeditor创建一个简单的数据流图: ```python from nodeeditor.node_editor_widget import NodeEditorWidget from nodeeditor.utils import dumpException try: # 创建一个节点编辑器窗口 nodeEditor = NodeEditorWidget() # 创建两个节点 node1 = nodeEditor.createNode("Node", pos=(80, 80)) node2 = nodeEditor.createNode("Node", pos=(320, 80)) # 创建连接 nodeEditor.createConnection(node1.outputs()[0], node2.inputs()[0]) # 显示节点编辑器窗口 nodeEditor.show() except Exception as e: dumpException(e) ``` 这个示例创建了一个包含两个节点的数据流图,节点之间通过连接进行数据传递。你可以根据自己的需求添加更多的节点和连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值