0
\$\begingroup\$

I wish to build a simple game in Unity such that the objects in the game can be controlled via a Python script (or a code in any other programming language). Is this possible? If yes then how? If no then are there any other alternatives to achieve similar results?

To make it more clear, say that I have 10 objects in my current scene. What I wish to do is to address each object individually via Python. One way of doing this is setting up keyboard bindings to select a particular object and then using keyboard and mouse events to control this object. But, is there a more cleaner (a native) way of doing the same?

\$\endgroup\$
11
  • \$\begingroup\$ Like you want to load and run a python script at runtime? \$\endgroup\$
    – ssb
    Jun 7, 2016 at 4:47
  • \$\begingroup\$ @ssb nope thats not what I meant. I mean the controller of the game is a Python script (i.e I write scripts to control the game objects) \$\endgroup\$
    – ironstein
    Jun 7, 2016 at 4:48
  • \$\begingroup\$ So you want to use a python script to provide automated input instead of a human player? \$\endgroup\$
    – ssb
    Jun 7, 2016 at 4:49
  • \$\begingroup\$ @ssb Thats exactly what I want. \$\endgroup\$
    – ironstein
    Jun 7, 2016 at 4:50
  • \$\begingroup\$ you can add IronPyton to your unity project and then create a c# script that will load python scripts from files and run them. I found this tutorial and it seems easy enough.link Then I guess you can import UnityEngine.dll into a IronPythong script and use the unity stuff like FindGameObjectWithTag and so on. \$\endgroup\$
    – Uri Popov
    Jun 7, 2016 at 11:21

3 Answers 3

3
\$\begingroup\$

Ok so first follow this tutorial. Then i wrote some code to try and test it out. C# code. I used the editor example from the tutorial but you can make it run during runtime or what ever:

 [MenuItem("Python/LoadFromFile")]
    public static void ReadFile()
    {
        var ScriptEngine = IronPython.Hosting.Python.CreateEngine();
        var ScriptScope = ScriptEngine.CreateScope();
        ScriptEngine.Runtime.LoadAssembly(typeof(GameObject).Assembly);
        ScriptEngine.Runtime.LoadAssembly(typeof(Editor).Assembly);
        StringBuilder example = new StringBuilder();
        FileInfo pySourceFile = new FileInfo("PyExampleString.txt");
        StreamReader reader = pySourceFile.OpenText();
        while(!reader.EndOfStream)
        {
            example.AppendLine(reader.ReadLine());
          //  Debug.Log(reader.ReadLine());
        }
       
        reader.Close();
        var ScriptSource = ScriptEngine.CreateScriptSourceFromString(example.ToString());
        ScriptSource.Execute(ScriptScope);
    }

Then I had to read how to do if statements in phyton and got one indentation error but I ended up with this in a .txt file named PyExampleString.txt

import UnityEngine as unity
if unity.GameObject.FindGameObjectWithTag("Test"):
    unity.Debug.Log("Found one")

This is tested and logs Found one if there is a game object with a tag Test in the scene. Hope you find this helpfull.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks a lot, appreciate it. And may I suggest, learn Python. Its fun ;) \$\endgroup\$
    – ironstein
    Jun 7, 2016 at 15:14
1
\$\begingroup\$

I hope I understood your question correctly. What I gathered was that you have an Unity game, and you want to have a Python script that provides input to the game instead of a human playing the game. Is that right?

In that case, yes, you can use a Python script to provide input to the game. The task isn't very pleasant, but yes, it can be done. Basically what you are looking for is a way to generate regular OS input events: mouse movement and clicks, key presses and releases, and perhaps even controller input events (all though this might be the hardest one to implement). Now, generating these events isn't something you can easily do in a cross-platform manner, so I'll only go trough some options you have for Windows.

There are libraries from Python that allow you to interact with the underlying Windows libraries. You might want to take a look at pywin32, and investigate the WinAPI on how to generate key events. A quick google search also showed me this SO answer which does exactly what you are looking for. You would then extend that piece of code posted on the great answer.

And this task can be also achieved with other languages, as long as there is a way to generate OS input events in the language in question.

\$\endgroup\$
3
  • \$\begingroup\$ Thank you for your reply. Although this is a perfectly sound way of solving the problem, is there some way in which the Python script can address individual unity game objects? For example, if there are 10 objects in the scene, I wish to control all of them independently. I could use keyboard bindings to select an objects and the use keyboard or mouse events to control this object, but is there some cleaner way? \$\endgroup\$
    – ironstein
    Jun 7, 2016 at 9:10
  • \$\begingroup\$ Probably yeah. Selecting individual objects might be hard. I'm kinda wondering why would you want a cleaner way to do this when you are already looking for more trouble with doing this outside of Unity. The most clean and native way to do this would be to do this with C# in Unity. \$\endgroup\$
    – user35344
    Jun 7, 2016 at 10:05
  • \$\begingroup\$ It is true that I could write the code directly in C# in unity, but then that would defeat the intention. My intention is to build a game and provide an interface to the game such that the game can be played by writing python scripts. So, the scripting part would be done after the entire game is already built (and would not require an installation of Unity, which is too big). \$\endgroup\$
    – ironstein
    Jun 7, 2016 at 13:44
0
\$\begingroup\$

Yes you can, but instead of working directly with pywin32 for Windows which is a pain in the ass you can use pywinauto, it allows you to send mouse and keyboard actions to windows accesing their widgets/controls directly, which is better but it's not crossplatform just for Windows.

Or you can use PyAutoGUI for (Windows, OSX, Linux), which instead of sending the input to a specific window or dialog I think it works like if you 'capture' the screen and you send the inputs in a determined position, so the window must be visible in front of any other thing.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .