Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  3. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Python For Unity Out of Process API Inconsistent Running Times

Discussion in 'Formats & External Tools Previews' started by npat15, Feb 24, 2021.

  1. npat15

    npat15

    Joined:
    Aug 21, 2020
    Posts:
    1
    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:
    Code (CSharp):
    1.  // define column values
    2.             col1 = "0";
    3.             col2 = "1";
    4.             col3 = "2";
    5.  
    6.             string col_assingment_1 = "col1 = " + col1;
    7.             string col_assingment_2 = "col2 = " + col2;
    8.             string col_assingment_3 = "col3 = " + col3;
    9.  
    10.  
    11.             string[] args = {  
    12.             "import numpy as np",
    13.                                
    14.             "file = open('Assets/Datasets/normal_data.csv', 'r')",
    15.             "matrix = np.loadtxt(file, delimiter=',', skiprows=1)",
    16.  
    17.             col_assingment_1,
    18.             col_assingment_2,
    19.             col_assingment_3,
    20.  
    21.             "col1 = matrix[:, col1]",
    22.             "col2 = matrix[:, col2]",
    23.             "col3 = matrix[:, col3]",
    24.             "col_len = len(col1)",
    25.  
    26.             "file.close()"
    27.             };
    28.  
    29.             // time metric
    30.             System.DateTime epochStart = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
    31.             int cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
    32.  
    33.             Debug.Log("Starting Python executions at: " + cur_time);
    34.  
    35.             foreach (string arg in args)
    36.             {
    37.                 Debug.Log(arg);
    38.                 PythonRunner.CallServiceOnClient(ClientName, "exec", arg);
    39.             }  
    40.  
    41.             cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
    42.             Debug.Log("Python evauluations starting at " + cur_time);
    43.  
    44.             // Py.GIL block needed for stability according to docs
    45.             using (Py.GIL()) {
    46.                 // get column arrays
    47.                 dynamic col1 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col1");
    48.                 dynamic col2 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col2");
    49.                 dynamic col3 = PythonRunner.CallServiceOnClient(ClientName, "eval", "col3");
    50.                 dynamic col_len = PythonRunner.CallServiceOnClient(ClientName, "eval", "col_len");
    51.  
    52.                 cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
    53.                 Debug.Log("Starting instantiation at " + cur_time);
    54.                 instantiate_objects(col1, col2, col3, col_len);
    55.  
    56.                 cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
    57.                 Debug.Log("Finished instantiation at " + cur_time);
    58.             }
    Where the "instantiate_objects" method looks something like this:
    Code (CSharp):
    1. public void instantiate_objects(dynamic xColumn, dynamic yColumn, dynamic zColumn, dynamic col_len)
    2.     {
    3.         // generate objects in scene based on column data
    4.  
    5.         for (int i = 0; i < (int)col_len; i++)
    6.         {
    7.             if (xColumn[i] != null && yColumn[i] != null && zColumn[i] != null)
    8.             {
    9.                 // create game object
    10.                 // TODO - work around hardcoding in sphere
    11.                 GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    12.                 obj.transform.position = new Vector3((float)xColumn[i], (float)yColumn[i], (float)zColumn[i]);
    13.             }
    14.         }
    15.     }
    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!
     
  2. markvi

    markvi

    Joined:
    Oct 31, 2016
    Posts:
    118
    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
     
  3. tran10

    tran10

    Joined:
    Nov 30, 2020
    Posts:
    13
    Hello,

    I have a script in C# for example:

    Code (CSharp):
    1. public class DraggableObject: MonoBehaviour
    2. {
    3. [INDENT]void OnMouseDown()
    4. {
    5. ....
    6. }[/INDENT]
    7. }

    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.
     
  4. markvi

    markvi

    Joined:
    Oct 31, 2016
    Posts:
    118