Python For Unity Out of Process API Inconsistent Running Times

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:

  1. My “exec” commands always run near-instantaneously
  2. My “eval” commands take 3-30 seconds to run
  3. 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!

Hi, we just published Python for Unity 4.0.0-exp.5 , which completely removes the out-of-process interpreter. Instead, in-process now works with native modules (including numpy & scipy). Please try it out!

cheers,
-Mark

Hello,

I have a script in C# for example:

public class DraggableObject: MonoBehaviour
{
[INDENT]void OnMouseDown()
{
....
}[/INDENT]
}

And I want to use AddComponent to add this script C# to gameObject by script python like this:

import UnityEngine as UE
go = UE.GameObject.CreatePrimitive(UE.PrimitiveType.Cube)
go.AddComponent(DraggableObject)

But I have the error : name ‘DraggableObject’ is not defined.
Do you have some advise? or I need to import DraggableObject.cs?

Thank you so much for your reponse.

Hoa.

I see you answered your own question in another thread, so I’ll just link to your excellent reply . :slight_smile: