Uniton lets you control the Unity game engine from Python. It aims to instrumentalize Unity and make it more useful in non-game applications.
pip install uniton
import uniton
# launch an example forest scene
ue = uniton.examples.Forest()
For more pre-built examples check uniton/examples!
Uniton requires Python 3.7+. We recommend the Anaconda/Miniconda distribution but it will work with others just as well. Install the Uniton Python package via pip install uniton
.
To use Uniton with your own Unity project, simply drop the – uniton.dll – into your project's Asset
folder.
Uniton also comes with pre-built example environments that automatically download when they are first used. Below are two examples but there are more. Check out uniton/examples!
# The kart game from the demo video
ue = uniton.examples.KartGame()
# A higher fidelity scene
ue = uniton.examples.Temple()
Any Unity project can become a Uniton project simply by dropping the uniton.dll
somewhere into the project's asset folder.
Connect to your a running Unity app
To launch and connect to a Uniton app do
import uniton
ue = uniton.UnityEngine(path='path/to/binary')
ue = uniton.UnityEngine()
# Alternatively, to connect to a remote Uniton app do, e.g.
ue = uniton.UnityEngine(host='192.168.1.101', port=10001)
# The remote Uniton app can been launched via, e.g. 'UNITONHOST="0.0.0.0" UNITONPORT=10001 path/to/binary'
# Warning: UNITONHOST="0.0.0.0" should only ever be used in a private and secure network!
# It theoretically allows everyone on the network to control the host.
ue.pause() # this can block the whole window when used in the Unity editor
ue.step() # advances game time by ue.time.delta and renders one frame
# more steps, etc..
ue.resume() # resume real time operation
ue.scene.<GameObjectName>.<ChildGameObjectName>
# Access components within game objects using lower camelcase
ue.scene.<GameObjectName>.<componentName> # e.g. rigidbody, boxCollider, camera, light
# Transform attributes are directly available on the game object, e.g.
ue.scene.<GameObjectName>.position == ue.scene.<GameObjectName>.transform.position
ue.<namespace>.<classname>
# The 'UnityEngine' namespace can be omitted, i.e.
ue.<classname> == ue.UnityEngine.<classname>
# Instantiate any C# class by calling it, as is usual in Python, e.g.
v = ue.Vector3(0, 1, 0)
v.x # returns a placeholder object for the 'x' property of a C# Vector3 object
v.x.py # immediately returns a promise object and triggers the value of 'v.x' to be sent to Python asynchronously
v.x.py() # blocks until the value has been received and returns the value
# Currently, only a few types can be received directly, e.g. int, float, str, byte arrays.
from uniton import QueuedRenderer
renderer = QueuedRenderer(ue.scene.Main_Camera.Camera, width=512, height=256, render_steps=4, ipc_steps=3)
frame = renderer.render() # will return a Numpy array of shape (256, 512, 3) and dtype 'uint8'
Internally, the frame is produced as follows.
Unity GPU (render) --render_queue--> Unity CPU --ipc_queue--> Python
Therefore, frame
actually shows the state of the game a number of renderer.render()
-calls earlier. To be precise, that number is
renderer.delay() == render_steps + ipc_steps - 2
Consequently, the following will block and be slow but show the current state of the game.
renderer = QueuedRenderer(ue.scene.Main_Camera.Camera, width=512, height=256, render_steps=1, ipc_steps=1)
frame = render.render()
Uniton creates placeholder objects for C# objects and functions. When a placeholder C# function is called from Python it will immediately return a new placeholder for the return value. This new placeholder object can be immediately worked with. Should the C# function throw an exception such that the actual return value never materializes, then Uniton will throw a delayed exception in Python. Attribute and method lookups on placeholder objects work the same way, as these lookups are also just functions calls internally.
- Generic C# classes and functions can't be used (please open an issue if this is important to you)
- Python functions can't be registered as C# callbacks (please open an issue if this is important to you)
- There is currently no documentation beyond this readme
In case that you aren't using Anaconda you might have to replace the python
command with python3
and the pip
command with python3 -m pip
. To maximize compatibilty you can install Uniton via
python3 -m pip install uniton --upgrade --user
To remove Uniton including all example binaries that have been loaded run
python -m uniton delete_data
pip uninstall uniton
Uniton | |
---|---|
Interact live with all C# objects, functions, classes | 🔥 |
Autocomplete for all C# objects 1 | 🔥 |
Fast, asynchronous execution | 🔥 |
Precise control over game time | 🔥 |
Faster-than-real-time rendering and simulation | 🔥 |
No dependencies beyond Python and Unity | 🔥 |
Cool example environments | 🔥 |
Import custom C# code at runtime | 🧪 |
Import models at runtime 2 | 🧪 |
🔥 = available, 🧪 = work in progress
1 Autocomplete is available only during live-coding (e.g. python repl, ipython, jupyter notebooks).
2 Supports .obj
and .urdf
models.
Uniton is currently only partially open-source (https://pypi.org/project/uniton/). I probably will open-source all of it soon. In the meantime, if you need access to the source code, please contact me at simonramstedt+uniton@gmail.com