[英]How to communicate properly between unity c# scripts and android activity?
[英]How to make c# in Unity communicate with Python
我正在為 Unity 游戲制作 Q-Learning 機器人,機器人在 Python 中,游戲在 c# 中,如何讓這兩個程序交換任何類型的數據(即整數字符串 arrays 等)? 任何使 Python 和 c# 用於 Unity 通信的方法都可以解決我的問題,我可以將任何內容集成到我的代碼中。
我的Python版本是3.6。
這就是我用來在 unity 和 python 之間進行通信的。 來自不同來源/教程的混合。
(它對我有用,但一個已知的問題是當 python 出現錯誤時 Unity 會凍結。我已經寫了一個 try/catch 方法,它返回一個空字節數組,但這似乎不起作用。)
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 派生:
public class Turing : SocketFloat
調用 ServerRequest 從 Python 返回一個預測。
float[] prediction = ServerRequest(myArray)
我假設機器人和游戲是分開的並且可能是遠程進程。 對於雙向通信,您可以考慮使用一些消息中間件或 Web 服務。
我懷疑更大的問題出在 Unity 方面。 與大多數專有平台一樣,Unity 擁有自己的網絡 API。 我不確定在 Unity 中使用獨立的基於 http 或 tcp 的服務有多復雜。
Unity 文檔中的這一頁介紹了與非 Unity 應用程序的集成。 如果您想采用 Web 服務方式,Webhooks 將是您最好的選擇。
RabbitMQ 顯然有一個Unity3d 客戶端,你也許可以找到其他類似的開源項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.