Hi!
I’m using Python for Unity to try and generate objects in a scene based on data from a csv file - for example, if we have three columns filled with numerical data, for each row in the csv, I’m generating an object in my scene with its x-coordinate as the value in column 1, the y-coordinate as the value in column 2, etc. While this could easily be done using C#, my goal is to perform some data analysis before generating my objects - being able to use python libraries like numpy and scipy for this could in theory save a great deal of time.
I’m running the following script to do this:
// define column values
col1 = "0";
col2 = "1";
col3 = "2";
string col_assingment_1 = "col1 = " + col1;
string col_assingment_2 = "col2 = " + col2;
string col_assingment_3 = "col3 = " + col3;
string[] args = {
"import numpy as np",
"file = open('Assets/Datasets/normal_data.csv', 'r')",
"matrix = np.loadtxt(file, delimiter=',', skiprows=1)",
col_assingment_1,
col_assingment_2,
col_assingment_3,
"col1 = matrix[:, col1]",
"col2 = matrix[:, col2]",
"col3 = matrix[:, col3]",
"col_len = len(col1)",
"file.close()"
};
// time metric
System.DateTime epochStart = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
int cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
Debug.Log("Starting Python executions at: " + cur_time);
foreach (string arg in args)
{
Debug.Log(arg);
PythonRunner.CallServiceOnClient(ClientName, "exec", arg);
}
cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
Debug.Log("Python evauluations starting at " + cur_time);
// Py.GIL block needed for stability according to docs
using (Py.GIL()) {
// get column arrays
dynamic col1 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col1");
dynamic col2 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col2");
dynamic col3 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col3");
dynamic col_len = PythonRunner.CallServiceOnClient(ClientName, "eval", "col_len");
cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
Debug.Log("Starting instantiation at " + cur_time);
instantiate_objects(col1, col2, col3, col_len);
cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
Debug.Log("Finished instantiation at " + cur_time);
}
Where the “instantiate_objects” method looks something like this:
public void instantiate_objects(dynamic xColumn, dynamic yColumn, dynamic zColumn, dynamic col_len)
{
// generate objects in scene based on column data
for (int i = 0; i < (int)col_len; i++)
{
if (xColumn[i] != null && yColumn[i] != null && zColumn[i] != null)
{
// create game object
// TODO - work around hardcoding in sphere
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
obj.transform.position = new Vector3((float)xColumn[i], (float)yColumn[i], (float)zColumn[i]);
}
}
}
While running this code does what I want, I’ve noticed some inconsistencies with running it. Sometimes, this script only takes a few seconds to run, and sometimes it takes up nearly 2 minutes! Added some Debug statements after certain parts of the code to try and see what was causing the bottleneck, and found this:
- My “exec” commands always run near-instantaneously
- My “eval” commands take 3-30 seconds to run
- Instantiating the objects takes 3-60 seconds to run.
Does anyone know why I could be having such inconsistent runtimes, and more importantly, a way to consistently get the quickest runtimes possible? My best guesses are some kind of cache for the “eval” commands that make it sometimes run faster, but I have no clue why instantiating objects is behaving so erratically.
Thank you!