PythonとUnity間の通信実装【ソケット実装】

最近取り組んだプロジェクトでは Python と Unity 間のデータ通信が必要で、Unity には IronPython や PyUnity などの Python プラグインもありますが、Python 環境とモデルは WSL2 で構成されていたため、Socket 通信を使用することにしました。
 

1.Pythonで接続と送信を実装

np の 2 次元/1 次元配列をリスト型に変換し、2 つの数値の間に「,」を分割して挿入して文字列型に変換し、UTF-8 でエンコードされたバイト ストリームに変換するというアイデアです。 、ソケット経由で送信します。

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

2. 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 バイト)を string 型に変換するため、浮動小数点数の長さが 10 の場合、10 バイト必要になりますが、ソケットの 1 回の送信には制限があります。大量のデータを送信する必要があるため、ここでは複数回の連続送信を使用し、1 回受信すると受信成功として 0 を返します。

おすすめ

転載: blog.csdn.net/cycler_725/article/details/130371012