- Home /
StreamReader in Unity not working properly
I recently tried writing a programm in two different languages. Basicaly doing some image-processing in python and then passing the result over to C#
not the entire image, just a vector2 calculated after doing the image-processing). But the problem is, this should happen as often as possible, since the image is actually a video. So the python script should look at every frame, process it and then output the result as a vector2. So far, so good, I was able to get that working.
But then I want the C# script to recognize if the python script outputs something, and print the output in realtime. I watched a tutorial about that and copied the idea to start a new Process and redirect the output. Then I used the OutputDataReceived
-event from the process to log the output whenever something was written to the Stream.
Here is the script for that:
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace PythonProcessing
{
public delegate void StreamReciever(string message);
public class Stream
{
StreamReader reader;
string result;
string file_path;
string python_path;
public int frame;
public event StreamReciever OnMessageRecieved;
public Stream(string file_path, string python_path)
{
this.file_path = file_path;
this.python_path = python_path;
}
public Process Start()
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = python_path + "/python.exe";
start.Arguments = string.Format("{0}", file_path);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = start;
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
UnityEngine.Debug.Log($"Data recieved! at {frame}");
OnMessageRecieved("Data: " + e.Data);
}
});
process.Start();
process.BeginOutputReadLine();
return process;
}
}
}
I then simply started the Process from a MonoBehaviour-Script sitting on an object in the scene, and subscribed to the OnMessageRecieved
-event i've created.
Here's the MonoBehavour-script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PythonProcessing;
using System;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
public class PythonReciever: MonoBehaviour
{
Stream stream;
Process process;
public string request;
public string output;
public int frame;
void Start()
{
stream = new Stream(true, "C:\\Users\\wanja\\Desktop\\HandTracking\\main.py", Application.dataPath + "/Python");
stream.OnMessageRecieved += Rec;
process = stream.Start();
}
void Update()
{
frame = Time.frameCount;
stream.frame = frame;
}
private void Rec(string message)
{
Debug.Log($"message {frame}");
output = message;
}
}
I thought this could work, but it doesn't behave as expected. The python-script starts, and runs smoothly (I'm displaying every frame to be able to see that). Unity also runs smoothly, I can switch between the image-window and unity no-problem. I can also do stuff in Unity while it's running, so it doesn't seem to have any trouble while runtime. There are also no error-messages, but I don't recieve any messages from the python script at first. Then after about 2000 frames I get about 800 messages in just a few frames, and then it's quiet again for another 2000 frames. Then I get about 800 messages again and this seems to just repeat forever. When I manually close the python-programm while leaving the unity-player running, the messages also instantly appear. So it seems like the Stream is extremly lagging while both programms seem to do absolutely fine. I also had no trouble with this when I first tried it in a simple C# console-application. That's why I think it has something to do with Unity handling this stuff, but I have no idea what exactly could be the problem here. When I decided to log the frame-count as soon as the event is triggered, it seemed like the messages really get recognized pretty much all at once:
Any help on what might be the problem here or even how to solve it would be awesome.
,### I recently tried writing a programm in two different languages. Basicaly doing some image-processing in python and then passing the result over to C# ### (not the entire image, just a vector2 calculated after doing the image-processing). But the problem is, this should happen as often as possible, since the image is actually a video. So the python script should look at every frame, process it and then output the result as a vector2. So far, so good, I was able to get that working.
But then I want the C# script to recognize if the python script outputs something, and print the output in realtime. I watched a tutorial about that and copied the idea to start a new Process and redirect the output. Then I used the OutputDataReceived
-event from the process to log the output whenever something was written to the Stream.
Here is the script for that:
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace PythonProcessing
{
public delegate void StreamReciever(string message);
public class Stream
{
StreamReader reader;
string result;
string file_path;
string python_path;
public int frame;
public event StreamReciever OnMessageRecieved;
public Stream(string file_path, string python_path)
{
this.file_path = file_path;
this.python_path = python_path;
}
public Process Start()
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = python_path + "/python.exe";
start.Arguments = string.Format("{0}", file_path);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = start;
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
UnityEngine.Debug.Log($"Data recieved! at {frame}");
OnMessageRecieved("Data: " + e.Data);
}
});
process.Start();
process.BeginOutputReadLine();
return process;
}
}
}
I then simply started the Process from a MonoBehaviour-Script sitting on an object in the scene, and subscribed to the OnMessageRecieved
-event i've created.
Here's the MonoBehavour-script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PythonProcessing;
using System;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
public class PythonReciever: MonoBehaviour
{
Stream stream;
Process process;
public string request;
public string output;
public int frame;
void Start()
{
stream = new Stream(true, "C:\\Users\\wanja\\Desktop\\HandTracking\\main.py", Application.dataPath + "/Python");
stream.OnMessageRecieved += Rec;
process = stream.Start();
}
void Update()
{
frame = Time.frameCount;
stream.frame = frame;
}
private void Rec(string message)
{
Debug.Log($"message {frame}");
output = message;
}
}
I thought this could work, but it doesn't behave as expected. The python-script starts, and runs smoothly (I'm displaying every frame to be able to see that). Unity also runs smoothly, I can switch between the image-window and unity no-problem. I can also do stuff in Unity while it's running, so it doesn't seem to have any trouble while runtime. There are also no error-messages, but I don't recieve any messages from the python script at first. Then after about 2000 frames I get about 800 messages in just a few frames, and then it's quiet again for another 2000 frames. Then I get about 800 messages again and this seems to just repeat forever. When I manually close the python-programm while leaving the unity-player running, the messages also instantly appear. So it seems like the Stream is extremly lagging while both programms seem to do absolutely fine. I also had no trouble with this when I first tried it in a simple C# console-application. That's why I think it has something to do with Unity handling this stuff, but I have no idea what exactly could be the problem here. When I decided to log the frame-count as soon as the event is triggered, it seemed like the messages really get recognized pretty much all at once:
Any help on what might be the problem here or even how to solve it would be awesome.
Your answer

Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Object from list in scriptableobject in list 0 Answers
How to make buttons have sound when it is highlighted and clicked? 0 Answers
Dictionary in second script empty 1 Answer