AI-Driven DCC Pipeline:
Controlling Maya & UE5 from Python

How I built a fully scripted, bidirectional Maya ↔ UE5 pipeline from scratch — no manual clicking, full AI feedback loop with live viewport screenshots.

✅ Fully Working — Tested in Production

One of the most friction-heavy parts of any game or film pipeline is the handoff between DCC applications — the moment you need to take something from Maya and get it into Unreal Engine 5, or pull it back for a round of edits. Traditionally this involves exporting files manually, navigating import dialogs, confirming settings, and hoping the scale is correct.

I decided to eliminate every one of those manual steps. The result is a fully scripted, AI-controlled pipeline where I can describe what I want in plain language, and Python code executes it directly inside both Maya and UE5 — with visual feedback captured as screenshots so the AI can literally see what it built.

The Two Connections

The foundation of everything is establishing a reliable two-way Python connection to each application.

Maya: Command Port

Maya has a built-in commandPort — a TCP socket server that accepts Python code and returns the result. One snippet in userSetup.py opens it on every launch:

import maya.cmds as cmds
cmds.commandPort(
    name="localhost:7001",
    sourceType="python",
    noreturn=False,    # send return values back
    echoOutput=False   # bypasses a Maya 2023 crash bug
)

From there, any external Python script can open a TCP socket, send code, and read the response back. It supports persistent connections — one socket, many commands — and returns values as strings, making it ideal for querying scene state.

UE5: Reverse TCP via Remote Execution

UE5 is more involved. Its Remote Execution plugin doesn't accept inbound connections — instead, it calls back to you. The handshake works like this:

Python ──UDP multicast ping──► UE5
Python ◄──pong (node ID)────── UE5
Python ──open_connection────► UE5
Python ◄──TCP connection back─ UE5
Python ──JSON command────────► UE5 executes Python
Python ◄──JSON result + output UE5

The key discovery: the entire protocol is pure JSON over UDP/TCP. No binary headers, no compiled dependencies. Once I reverse-engineered the message structure from the UE5 C++ source, I could implement it in about 200 lines of stdlib Python.

"The hardest part wasn't the code. It was macOS dropping UDP multicast packets on the loopback interface."

On macOS, UE5's multicast packets get silently dropped when sent to 127.0.0.1. The fix: always bind and broadcast using the machine's physical network interface IP (e.g. en0), not loopback. And critically — disable "Use Less CPU when in Background" in Unreal's preferences, or the Editor throttles its network stack and stops responding.

The FBX Pipeline Bridge

With both connections working, the asset transfer pipeline takes shape as a four-script system sharing a handoff folder at ~/Desktop/MayaToUE5/.

Maya ──maya_export_fbx.py──► FBX file ──ue5_import_fbx.py──► UE5

UE5 ──ue5_export_for_maya.py──► FBX file ──maya_import_fbx.py──► Maya

Stage 1 — Maya to UE5

A Python script connects to Maya, creates geometry (or selects existing objects), then fires a MEL FBX export command:

mel.eval('FBXResetExport')
mel.eval('FBXExportUpAxis y')
mel.eval('FBXExport -f "/path/to/asset.fbx" -s')  # -s = selected

The FBX lands in the shared folder. Immediately after, a second script connects to UE5 and imports it using unreal.AssetImportTask with FbxImportUI options — no dialog, no confirmation, fully automated. The asset appears in the Content Browser at /Game/MayaAssets/ and an actor is spawned in the level.

Stage 2 — UE5 back to Maya

The reverse direction completes the loop. UE5's Python API finds the actor by label, exports its Static Mesh as FBX via unreal.AssetExportTask, and Maya imports it back for editing. After edits, the original Stage 1 scripts push it back to UE5 with replace_existing=True.

The Critical Scale Rule

The first test import looked correct in the logs but appeared as a nearly invisible dot in the UE5 viewport. The reason: Maya 1 unit = UE5 1 cm. A polyCube with w=4 is 4cm wide — essentially microscopic at game scale.

The fix is simple once you know it: always model at real-world centimetre scale in Maya. A door is 200 units tall. A human character is about 180 units. With that in mind, the asset appeared correctly in UE5 on the next import.

Phase 4: Skeletal Mesh & Skinning

Once the static mesh bridge was stable, I tackled the most complex data type: Skeletal Meshes. Unlike static geometry, these require transferring joint hierarchies, bind poses, and per-vertex skinning weights.

The "Human" Stress Test

To prove the pipeline's robustness for production assets, I ran a full roundtrip with a complex human skeletal mesh. The process: Import human.fbx to Maya → Auto-export as humanMaya.fbx → Auto-import to UE5.

The AI Feedback Loop

The most interesting part of this system isn't the asset transfer — it's the visual feedback loop that lets an AI agent see the results of its own work.

After any scene modification, a single call to ue_client/feedback.py does three things:

  1. Scene query — queries all actors in the level, returns class counts and labels
  2. Camera positioning — moves the UE5 Editor viewport to four preset angles (wide front, diagonal, top-down, street level)
  3. Screenshot capture — calls unreal.AutomationLibrary.take_high_res_screenshot() at 1920×1080 and copies the PNGs to a local folder

The AI can then load those screenshots, analyze the geometry visually, identify issues like wrong scale, incorrect orientation, missing parts, or poor composition — and plan the next script accordingly. This closes the loop from "write code" to "see the result" without any manual step.

"The AI doesn't just read logs. It views the scene like an artist would — from multiple angles — and plans the next edit based on what it sees."

The Reality of Building This: Dealing with "AI Hallucinations"

It is worth noting that automating Unreal Engine via Python as an AI agent involves significant debugging and trial-and-error. The UE5 Python API is massive, frequently updated, and sometimes poorly documented for edge cases. During the development of this very pipeline, I encountered several "hallucinations"—attempting to use intuitive but non-existent or deprecated methods.

For example, when trying to clear the viewport for a clean skeletal mesh screenshot, I assumed a standard actor.destroy() method existed on the SkeletalMeshActor, resulting in an ENGINE_ERROR: 'SkeletalMeshActor' object has no attribute 'destroy' in the Message Log. The correct, but less obvious, Unreal API call is unreal.EditorLevelLibrary.destroy_actor(actor).

This highlights why the visual feedback loop and clear error logging are so critical in an AI-driven pipeline. When an agent hallucinates an API call, it must be able to read the resulting stack trace, correct its assumption, and rewrite the script to succeed.

Skill Files: Teaching a Fresh AI Session

Each capability in this pipeline is documented as a SKILL.md — a structured markdown file that sits at .agent/skills/skill_name/SKILL.md in the repository. When a new AI session starts, it reads the relevant skill and immediately knows: which files to run, what the scale rules are, what the common failure modes look like, and exactly how to interpret the feedback.

This pattern — skills as persistent, versioned knowledge — means the system gets smarter over time without relying on conversation history. Each session starts informed rather than blank.

What's Next

The current pipeline handles Static Meshes. The natural progression is:

  • Material transfer — mapping Maya shader networks to UE5 Material Instances automatically
  • Batch processing — an asset list that exports multiple meshes in a single session
  • Scene comparison — diffing two feedback captures to detect what changed between iterations

The repos are open source: DC_UEDev (UE5 Python client) and DC_MayaDev (Maya Command Port client).

← BACK TO BLOG