I am quite new to Unity and i am currently using it as a tool for designing a simple simulated environment for my pilot research study. Here is a simplified explanation:
The main character (agent) scans the environment and sends the state (as a JSON object) via TCP socket to a python server.
On the python server side a big calculation is performed based on the the state. The result is an action that is being sent back via TCP to Unity.
The character needs to perform this action in Unity and then again scan the environment. The new state is sent again to the python server....
This process is being repeated 'till infinity (unless the client or server is stopped) eventually leading to the agent self-developing a behavior based on its learning.
I finished creating the environment in unity as well as programmed the learning algorithm in python. Moreover, i managed to establish TCP connection between the two. However, i stumbled across the problem of the main Update() loop in Unity.
Namely, if i simplify the process to Unity sending ping (being the state) and python sending pong (being the action) i need the following process to be repeated.
- freeze frame
- ping
- calculation
- pong
- next frame
So in the Unity Start()
method i setup the socket and send the initial ping. What i would like in the main Update()
loop is to make Unity wait for python's pong answer before updating the frame. I created a script containing a toy example and tried to simulate the calculation-time in python by adding 2 seconds of delay before sending the pong to Unity.
Here is the code for the Unity script (just attach it to the Main Camera):
using UnityEngine;
using System;
using System.IO;
using System.Net.Sockets;
public class networkSocketPingPong : 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();
writeSocket("ping");
}
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 from Python");
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;
socket_writer.Write(line);
socket_writer.Flush();
}
//... reading from a socket...
public String readSocket()
{
if (!socket_ready)
{
Debug.Log("Socket is not 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;
}
}
...and here is the python server code:
import socket
import time
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":
time.sleep(2)
print ("Unity Sent: " + str(data))
client.send("pong\n")
else:
client.send("Bye!")
print ("Unity Sent Something Else: " + str(data))
client.close()
break
I first run the python server and then the simulation (via Unity editor). This results with the following console screenshot:
This proves that the main Update() loop is running while i want it to pause and update only when "pong" is received from the server. Any ideas how to achieve this?
I searched the forum for answers but always stumbled upon questions that ask for the opposite - how to make Unity not to freeze - and answers that suggest using Coroutines or Threads.
Any help will be much appreciated.
Thanks in advance!!!