问题描述
我正在为Unity游戏制作Q-Learning机器人,该机器人使用Python,而游戏使用c#,如何使两个程序交换任何类型的数据(即整数字符串数组等)?使Python和Unity的c#进行通信的任何方法都可以解决我的问题,将任何内容集成到我的代码中都没有问题.
I'm making a Q-Learning bot for a Unity game, the bot is in Python and the game is in c#, how can I make the two programs exchange data of any kind (i.e integers string arrays etc)?Any way to make Python and c# for Unity communicate will solve my problem,I have no problem with integrating anything to my code.
另一个问题类似于我的问题,但是答案并没有从Python方面解释要做什么.
The other question is like mine, but the answer doesn't explain what to do from the Python side.
我的Python版本是3.6.
My Python version is 3.6.
推荐答案
这是我在unity和python之间进行通信所使用的内容.来自不同来源/教程的混合.
This is what I use for communication between unity and python. A mix from different sources/tutorials.
(它对我有用,但是一个已知的问题是,当python中出现错误时Unity会冻结.我已经编写了一个try/catch方法,该方法返回一个空字节数组,但似乎不起作用.)
(It works for me, but a known problem is that Unity freezes when there is an error in python. I already wrote a try/catch method that returns an empty bytearray, but that doesn't seem to work.)
C#脚本
using UnityEngine;
//using System.Net;
using System.Net.Sockets;
using System;
public class SocketFloat : MonoBehaviour
{
public string ip = "127.0.0.1";
public int port = 60000;
private Socket client;
[SerializeField]
private float[] dataOut, dataIn; //debugging
/// <summary>
/// Helper function for sending and receiving.
/// </summary>
/// <param name="dataOut">Data to send</param>
/// <returns></returns>
protected float[] ServerRequest(float[] dataOut)
{
//print("request");
this.dataOut = dataOut; //debugging
this.dataIn = SendAndReceive(dataOut); //debugging
return this.dataIn;
}
/// <summary>
/// Send data to port, receive data from port.
/// </summary>
/// <param name="dataOut">Data to send</param>
/// <returns></returns>
private float[] SendAndReceive(float[] dataOut)
{
//initialize socket
float[] floatsReceived;
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(ip, port);
if (!client.Connected) {
Debug.LogError("Connection Failed");
return null;
}
//convert floats to bytes, send to port
var byteArray = new byte[dataOut.Length * 4];
Buffer.BlockCopy(dataOut, 0, byteArray, 0, byteArray.Length);
client.Send(byteArray);
//allocate and receive bytes
byte[] bytes = new byte[4000];
int idxUsedBytes = client.Receive(bytes);
//print(idxUsedBytes + " new bytes received.");
//convert bytes to floats
floatsReceived = new float[idxUsedBytes/4];
Buffer.BlockCopy(bytes, 0, floatsReceived, 0, idxUsedBytes);
client.Close();
return floatsReceived;
}
}
Python代码
import socket
import struct
import traceback
import logging
import time
def sending_and_reciveing():
s = socket.socket()
socket.setdefaulttimeout(None)
print('socket created ')
port = 60000
s.bind(('127.0.0.1', port)) #local host
s.listen(30) #listening for connection for 30 sec?
print('socket listensing ... ')
while True:
try:
c, addr = s.accept() #when port connected
bytes_received = c.recv(4000) #received bytes
array_received = np.frombuffer(bytes_received, dtype=np.float32) #converting into float array
nn_output = return_prediction(array_received) #NN prediction (e.g. model.predict())
bytes_to_send = struct.pack('%sf' % len(nn_output), *nn_output) #converting float to byte
c.sendall(bytes_to_send) #sending back
c.close()
except Exception as e:
logging.error(traceback.format_exc())
print("error")
c.sendall(bytearray([]))
c.close()
break
sending_and_reciveing()
如果要发出请求,请让您的Unity脚本(正在使用的脚本)从SocketFloat派生:
If you want to make a request, let your Unity script (the one you are working with) derive from SocketFloat:
public class Turing : SocketFloat
调用ServerRequest返回来自Python的预测.
Calling ServerRequest returns a predictions from Python.
float[] prediction = ServerRequest(myArray)
这篇关于如何使Unity中的C#与Python通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!