Dear community,
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 simulation
- ping
- calculation
- pong
- unfreeze simulation
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
")
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!!!