unity3d 使用TCP套接字将数据从Unity(C#)传输到Python,反之亦然

osh3o9ms  于 2023-02-05  发布在  C#
关注(0)|答案(1)|浏览(262)

So I am relatively new to Unity and socket communications. I have a unity scene from which I want to send some robot position (Vector3) and some other float data to python over tcp socket. I also want to send some control actions (float data) from python to Unity.
On python side I have:

import socket
import time

class connect_class(object):
    
    host = "127.0.0.1"
    port = 25001
    sock = []

    def connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.host, self.port))
        except Exception: 
            print("Connection Error, Check if Unity scene is running.")

class communication_class(object):
    connect_cl = connect_class()
    connect_cl.connect()
    sock = connect_cl.sock

    def receive(self):
        self.receivedData = self.sock.recv(1024).decode("UTF-8") 
        print(self.receivedData)

cl = communication_class()
cl.receive()

The result I am getting is: When I call the receive() for the first time.
{"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]}
However If I call receive() multiple times after that, the same data is just aggregated, as shown below.
{"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.728967666625978,"z":-23.946182250976564}]} {"robot_pos":[{"x":-7.992547035217285,"y":21.72896766662
I would like to receive only the complete vector only once whenever I call receive.
On the Unity (C#) side I have:

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
using System.Threading;
using System.IO;

public class comm : MonoBehaviour
{
    Thread mThread;
    public string connectionIP = "127.0.0.1";
    public int connectionPort = 25001;
    IPAddress localAdd;
    TcpListener listener;
    TcpClient client;
    Vector3 receivedPos = Vector3.zero;
    public GameObject robot;
    public Vector3 robot_pos;

    

    bool running;

    public string SaveToString()
    {
        return JsonUtility.ToJson(this);
    }

    public class JsonData
    {
        public List<Vector3> robot_pos = new List<Vector3>();
    }

    private void Update()
    {
        transform.position = receivedPos; //assigning receivedPos in SendAndReceiveData()
        robot_pos = robot.transform.position;

    }

    private void Start()
    {
        robot = GameObject.Find("robot");
        ThreadStart ts = new ThreadStart(GetInfo);
        mThread = new Thread(ts);
        mThread.Start();
    }

    void GetInfo()
    {
        localAdd = IPAddress.Parse(connectionIP);
        listener = new TcpListener(IPAddress.Any, connectionPort);
        listener.Start();

        client = listener.AcceptTcpClient();

        running = true;
        while (running)
        {
            SendData();
            //SendAndReceiveData();
        }
        listener.Stop();
    }

    void SendData()
    {   
        
        NetworkStream nwStream = client.GetStream();
        StreamWriter sw = new StreamWriter(nwStream) { AutoFlush = true };
        var testData = new JsonData();
        testData.robot_pos = new List<Vector3>()
        {
            robot_pos
        };
        var result = JsonUtility.ToJson(testData);

        //---Sending Data to Host----
        sw.WriteLine(result);
        //string data = robot_pos.ToString();
        //sw.Write(data, 0, data.Length);

    }
}

I am not sure how to just receive complete current robot position once per receive() call.
I would appreciate any help or if there are any other better ways to do it.
I tried to use streamwriter.flush() however it also dosent work.

ohfgkhjo

ohfgkhjo1#

看起来您的问题在这里:

while (running)
{
    SendData();
    //SendAndReceiveData();
}

这只会在一个循环中永远发送相同的数据。
如果您只想让它在侦听器连接时发送一次位置,那么就删除while循环,只发送一次SendData,然后关闭套接字并等待另一个连接。

相关问题