Of course! Using Python with Unity is a powerful and increasingly popular workflow. Here’s a comprehensive guide covering the main methods, their pros and cons, and practical examples.

The Core Concept: How Python and Unity Interact
It's crucial to understand one fundamental thing: You cannot run Python scripts inside a standalone Unity build (like for PC, Mac, or mobile).
Unity is built on C#, and its engine is compiled to native code. Python is an interpreted language that requires its own runtime environment.
Therefore, the interaction between Python and Unity happens externally. Your Unity game acts as a "server," and your Python scripts act as "clients" that send and receive data. This is primarily achieved through Inter-Process Communication (IPC).
The most common and effective methods for this are:

- Unity-Python Bridge (UPB): A dedicated library designed for this purpose.
- gRPC: A high-performance, open-source framework for RPC (Remote Procedure Calls).
- Sockets: The low-level, traditional way to send data over a network (even if it's just on your local machine).
- Command-Line Arguments: For simple, one-way communication when the game starts.
- ML-Agents: A specialized use case for training AI/ML models with Python.
Let's break down the top methods.
Method 1: The Unity-Python Bridge (UPB) - Recommended for Beginners
This is the most straightforward method for getting started. It's a library that handles the complex serialization and communication for you.
How it Works:
UPB provides C# scripts for Unity and Python libraries that communicate over a local network port (localhost).
Step-by-Step Guide:
Part A: Unity Setup
-
Install the Package:
- In the Unity Editor, go to Window > Package Manager.
- Click the icon and select "Add package from git URL...".
- Enter the URL:
https://github.com/Kyle-Dorman/Unity-Python-Bridge.gitand click "Add".
-
Create a Communicator Object:
- In your scene, create an empty GameObject. Call it
PythonCommunicator. - Add the
PythonCommunicator.csscript to this GameObject. You can find it in the package's folder or by dragging it from the Project window.
- In your scene, create an empty GameObject. Call it
-
Write C# Code to Send/Receive Data:
- The
PythonCommunicatorhas two main events:OnMessageReceivedandOnObjectReceived.
Example C# Script (
PlayerController.cs):using UnityEngine; using UPB; // Make sure to include the UPB namespace public class PlayerController : MonoBehaviour { public PythonCommunicator communicator; // Drag the PythonCommunicator object here in the Inspector void Start() { // Subscribe to the event for receiving messages communicator.OnMessageReceived += HandleMessageFromPython; communicator.OnObjectReceived += HandleObjectFromPython; } void Update() { // Example: Send player position to Python every frame if (Input.GetKeyDown(KeyCode.Space)) { string positionData = $"Player is at: {transform.position.x}, {transform.position.y}, {transform.position.z}"; communicator.Send("unity_message", positionData); // Send a string } } private void HandleMessageFromPython(string message) { Debug.Log($"Received message from Python: {message}"); } private void HandleObjectFromPython(object obj) { // This is for receiving serialized objects. You need to know the type. // For example, if you send a Vector3 from Python, you'd cast it here. if (obj is Vector3 receivedVector) { Debug.Log($"Received Vector3 from Python: {receivedVector}"); transform.position = receivedVector; } } } - The
Part B: Python Setup
-
Install the Python Library:
- Open your terminal or command prompt and run:
pip install upb-python
- Open your terminal or command prompt and run:
-
Write Python Code to Send/Receive Data:
Example Python Script (
unity_connector.py):import upb import time import random # Connect to Unity on localhost, port 50001 connector = upb.UnityConnector(host="localhost", port=50001) print("Connected to Unity. Waiting for messages...") # Define a function to handle messages from Unity def on_message_received(message): print(f"PYTHON: Received message from Unity: '{message.data}'") # Define a function to handle objects from Unity def on_object_received(obj): print(f"PYTHON: Received object from Unity of type: {type(obj)}") # Subscribe to the events connector.on_message = on_message_received connector.on_object = on_object_received try: # Main loop to send data to Unity while True: # Send a simple string message every 2 seconds connector.send("python_message", f"Hello from Python! Time: {time.time()}") # Send a Vector3 object every 3 seconds if int(time.time()) % 3 == 0: vector_to_send = Vector3(random.uniform(-5, 5), 1, random.uniform(-5, 5)) connector.send("unity_object", vector_to_send) # Note: We send to 'unity_object' to be caught by OnObjectReceived in C# time.sleep(1) except KeyboardInterrupt: print("Disconnecting...") connector.disconnect()Note: You'll need to define the
Vector3class in your Python script or import it from a library like PyGame or NumPy.
Method 2: gRPC - For High Performance and Scalability
gRPC is a modern, high-performance RPC framework from Google. It's more complex to set up but is incredibly fast and robust, making it ideal for complex simulations, AI model inference, or multi-user applications.
How it Works:
- You define a service in a special language-agnostic file called Protocol Buffers (.proto).
- You use the
protoccompiler to generate C# and Python code from this.protofile. This gives you strongly-typed client and server stubs. - Your Unity game hosts the gRPC server.
- Your Python script acts as the client that calls functions on the Unity server.
Simplified Workflow:
-
Define the Service (
unity_service.proto):syntax = "proto3"; service UnityService { rpc GetPlayerPosition (PlayerRequest) returns (PositionResponse) {} rpc MovePlayer (MoveRequest) returns (EmptyResponse) {} } message PlayerRequest { int32 player_id = 1; } message PositionResponse { float x = 1; float y = 2; float z = 3; } message MoveRequest { int32 player_id = 1; float x = 2; float y = 3; float z = 4; } message EmptyResponse {} -
Generate Code:
- Install the protocol buffer compiler (
protoc). - Run
protocwith the C# and Python plugins to generate the service classes.
- Install the protocol buffer compiler (
-
Unity (Server):
- You'll need a gRPC server library for Unity (e.g.,
Grpc.Core). - Implement the
UnityServiceBaseclass and define the logic forGetPlayerPositionandMovePlayer.
- You'll need a gRPC server library for Unity (e.g.,
-
Python (Client):
- Use the generated Python stubs to create a client.
- Call
stub.GetPlayerPosition(request)orstub.MovePlayer(request).
Method 3: Sockets - The "From Scratch" Approach
This gives you the most control but requires you to handle serialization (turning data into bytes) and message framing yourself.
How it Works:
- Unity opens a
TcpListener(server). - Python opens a
TcpClient(client) and connects to Unity's IP and port. - They send data streams back and forth.
The Hard Part: Serialization
You can't just send a string like "Hello World". You need to agree on a format. A common format is JSON.
Example C# (Server):
using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
public class SocketServer : MonoBehaviour
{
TcpListener listener;
void Start()
{
listener = new TcpListener(System.Net.IPAddress.Loopback, 8080);
listener.Start();
Debug.Log("Socket server started. Waiting for a connection...");
Task.Run(AcceptClients);
}
async void AcceptClients()
{
while (true)
{
using (TcpClient client = await listener.AcceptTcpClientAsync())
using (NetworkStream stream = client.GetStream())
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Debug.Log($"Received JSON: {data}");
// You would use a JSON library like Newtonsoft.Json to parse this
// For example: var myObject = JsonConvert.DeserializeObject<MyClass>(data);
}
}
}
}
Example Python (Client):
import socket
import json
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8080 # The port used by the server
data_to_send = {"player_id": 1, "position": {"x": 10.5, "y": 0, "z": -5.2}}
json_string = json.dumps(data_to_send)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(json_string.encode('utf-8'))
print(f"Sent JSON to Unity: {json_string}")
Method 4: Command-Line Arguments
This is the simplest method, but it's one-way (from OS to Unity) and only runs at startup.
How it Works:
When you launch your Unity build from the command line, you can pass arguments. Unity's Application.argv array in C# will contain these arguments.
Example (Command Line):
# On Windows YourGame.exe --level 2 --difficulty hard # On macOS/Linux ./YourGame.app/Contents/MacOS/YourGame --level 2 --difficulty hard
Example C# (in Unity):
using UnityEngine;
public class StartupArgs : MonoBehaviour
{
void Start()
{
for (int i = 0; i < Application.argv.Length; i++)
{
Debug.Log($"Arg {i}: {Application.argv[i]}");
}
// Example: Check for a specific argument
if (System.Array.IndexOf(Application.argv, "--level") != -1)
{
int levelIndex = int.Parse(Application.argv[System.Array.IndexOf(Application.argv, "--level") + 1]);
Debug.Log($"Loading level {levelIndex}...");
// LoadScene(levelIndex);
}
}
}
Method 5: Unity ML-Agents
This is a specialized, official solution for training AI/ML models (like Reinforcement Learning models) in Python.
How it Works:
- You create "Academies" and "Agents" in your Unity scene.
- These agents observe the environment (e.g., camera images, game state) and take actions (e.g., move left/right).
- The Unity environment sends this data to a Python training environment.
- The Python environment (using libraries like PyTorch or TensorFlow) runs a learning algorithm and sends back decisions (actions) for the agents to take.
- This loop continues until the AI is trained.
This is not for general-purpose scripting but is the industry standard for creating AI behaviors for games.
Summary and Recommendation
| Method | Best For | Pros | Cons |
|---|---|---|---|
| Unity-Python Bridge (UPB) | Beginners, rapid prototyping, general-purpose communication | Very easy to set up, handles serialization, good performance for most cases. | Less performant than gRPC, less control than raw sockets. |
| gRPC | High-performance, scalable applications, AI inference | Extremely fast, strongly-typed, robust, supports streaming. | Steeper learning curve, more complex setup (.proto files, code gen). |
| Sockets | Full control, learning, custom protocols | Maximum flexibility, no external libraries needed (beyond a JSON lib). | Very complex to implement correctly (serialization, threading, error handling). |
| Command-Line Args | One-time configuration at game launch | Simple, built-in, no code needed in Python. | One-way communication, only at startup. |
| ML-Agents | Training AI/ML models for games | Official, powerful, designed specifically for this task. | Highly specialized, not for general scripting. |
My Recommendation:
- If you are new to this or want to quickly connect Unity and Python for data logging, AI control, or tools: Start with the Unity-Python Bridge (UPB). It's the fastest way to get results without getting bogged down in network details.
- If you are building a system that requires high throughput and scalability, like a backend for a multiplayer game or a complex AI simulation: Invest the time to learn gRPC. It's the professional standard for a reason.
