【发布时间】:2017-07-20 18:40:32
【问题描述】:
出于试点研究的目的,我尝试将 Unity 中的简单模拟环境与基于神经网络的 python 控制器连接起来。模拟 Unity 环境中的主角应根据其经验学习行为:
- 主角扫描环境并将其存储在数据结构中;
- 此数据结构通过 TCP 发送到 Python 中正在运行的服务器;
- 在 python 中执行复杂的计算(基于从 Unity 接收的数据)并产生结果(动作);
- 结果(操作)通过 TCP 发送回 Unity。角色执行与结果对应的动作。
- 重复步骤 1-4 直到无穷大(除非客户端或服务器停止)。
这个过程可以抽象为通过 TCP 发送 Ping - Pong 消息,其中 Unity 发送“Ping”,Python 进行一些计算并产生“Pong”,该“Pong”被发送回 Unity,更新模拟并再次产生一个“Ping”并将其发送到 python...
我目前在一个玩具项目中测试这个过程。我在 Unity 场景中的主摄像机上附加了一个脚本,如下所示:
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
using Newtonsoft.Json;
using System.Threading;
public class networkSocketSO : MonoBehaviour
{
public String host = "localhost";
public Int32 port = 50000;
internal Boolean socket_ready = false;
internal String input_buffer = "";
TcpClient tcp_socket;
NetworkStream net_stream;
StreamWriter socket_writer;
StreamReader socket_reader;
private void Start()
{
setupSocket();
}
void Update()
{
string received_data = readSocket();
switch (received_data)
{
case "pong":
Debug.Log("Python controller sent: " + (string)received_data);
writeSocket("ping");
break;
default:
Debug.Log("Nothing received");
break;
}
}
void OnApplicationQuit()
{
closeSocket();
}
// Helper methods for:
//...setting up the communication
public void setupSocket()
{
try
{
tcp_socket = new TcpClient(host, port);
net_stream = tcp_socket.GetStream();
socket_writer = new StreamWriter(net_stream);
socket_reader = new StreamReader(net_stream);
socket_ready = true;
}
catch (Exception e)
{
// Something went wrong
Debug.Log("Socket error: " + e);
}
}
//... writing to a socket...
public void writeSocket(string line)
{
if (!socket_ready)
return;
line = line + "\r\n";
socket_writer.Write(line);
socket_writer.Flush();
}
//... reading from a socket...
public String readSocket()
{
if (!socket_ready)
return "";
if (net_stream.DataAvailable)
return socket_reader.ReadLine();
return "";
}
//... closing a socket...
public void closeSocket()
{
if (!socket_ready)
return;
socket_writer.Close();
socket_reader.Close();
tcp_socket.Close();
socket_ready = false;
}
}
还有一个带有以下代码的python服务器:
import socket
import json
host = 'localhost'
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
print "Client connected."
while 1:
data = client.recv(size)
if data == "ping":
print ("Unity Sent: " + str(data))
client.send("pong")
else:
client.send("Bye!")
print ("Unity Sent Something Else: " + str(data))
client.close()
break
如果我启动服务器然后运行 Unity 项目,我会遇到奇怪的事情。即,python 服务器似乎不理解 Unity 客户端发送的“ping”字符串。此外,我希望 Unity 模拟中的帧在从 python 服务器接收到“Pong”消息之前不要更新。
我已经阅读了有关使用协程或线程的类似问题的解决方案,但我担心它会建立另一个“时钟”并导致没有真正的 ping-pong-updateframe-ping-pong-updateframe... 进程。
有什么想法吗?
提前致谢!!!
附:请记住,真正的消息不会是“Ping”和“Pong”,而是正确的 Json 对象。这只是一个简化。
编辑: 我首先启动 python 服务器,然后启动 Unity 模拟(在编辑器中)。 在 python 控制台上,我得到:
Client connected.
Unity Sent Something Else: ping
...这证明了我的说法是“python 不理解通过 Unity (C#) 发送的字符串”
在 Unity 控制台中我得到:
【问题讨论】:
-
这个问题不止一个。对于第一个:python 服务器是否收到任何东西?你的程序打印什么?
-
你能告诉我们当前代码发生了什么吗?
-
我刚刚使用 python 打印和 Unity 控制台日志编辑了原始问题。还有...感谢大家的回复。
-
你弄清楚如何以帧为基础进行通信了吗?
标签: python unity3d tcp simulation