Communication implementation between Python and Unity [Socket implementation]

The project I recently worked on required data communication between Python and Unity. Unity also has python plug-ins such as IronPython and PyUnity. However, my python environment and model were configured in WSL2, so I chose to use Socket communication.
 

1. Python implements connection and transmission

The idea is to convert an np two-dimensional/one-dimensional array into a list type, and then insert "," between two numbers as a split to convert it into a string type, convert it into a UTF-8 encoded byte stream, and send it through the socket.

Implementation of python part:

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接收数据后再发送下一个

2. Unity implements monitoring and transmission

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

Call the code of the above U2P class and hang it in an object in the scene:

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: 处理数据
            }
        }
    }
}

It should be noted that since this method converts the float type (4 bytes) to the string type, if a floating point number is 10 in length, it requires 10 bytes, but the single transmission of the socket is limited. , if a large amount of data needs to be transmitted, so multiple continuous transmissions are used here, and 0 is returned after receiving once as the acceptance is successful.

Guess you like

Origin blog.csdn.net/cycler_725/article/details/130371012