The same everyday TA task, written three times: Maya cmds, Blender bpy, Unreal Python. APIs differ; the thinking transfers. Learn a new DCC by mapping it onto the one you already speak.
| Maya cmds | Blender bpy | Unreal Python | |
|---|---|---|---|
| Everything is... | a string (node names) | an object (bpy.data) | an asset (packages on disk) |
| You mostly... | call flat commands on names | walk object properties | ask subsystems & libraries |
| Selection is... | central - most cmds act on it | context-dependent (the classic gotcha) | barely a thing - you work on asset paths |
| Classic gotcha | duplicate names break everything - use long paths | ops need the right context/mode | loading assets is slow - filter via the registry first |
Hold onto this: Maya asks "what is it called?", Blender asks "where does it live in the data?", Unreal asks "which subsystem owns this?". Once that clicks, the rest is documentation lookup.
import maya.cmds as cmds
BUDGET = 10000
for mesh in cmds.ls(type="mesh", noIntermediate=True, long=True):
tris = cmds.polyEvaluate(mesh, triangle=True)
if tris > BUDGET:
print(f"{mesh} {tris} tris")What transfers: the shape - enumerate, measure, compare, report. What doesn't: Maya counts via a query command on a name; Blender computes from raw geometry data (it hands you the polygons and shrugs); Unreal makes you load each asset, which is why real audit scripts filter with the registry before loading anything.
import maya.cmds as cmds
cmds.loadPlugin("fbxmaya", quiet=True)
cmds.file(r"D:/exports/prop.fbx", force=True,
exportSelected=True, type="FBX export",
options="v=0")What transfers: exports are configuration problems, not code problems - the flags are the work. What doesn't: the asymmetry. Maya and Blender are usually sources, Unreal a destination; a "pipeline" is mostly agreeing on the flags once and burying them in a shared preset so no human sets them again. (That's the Blender starter kit in one sentence.)
import maya.cmds as cmds, re
RULE = re.compile(r"^SM_[A-Z][A-Za-z0-9_]*$")
for xform in cmds.ls(type="transform", long=True):
short = xform.rsplit("|", 1)[-1]
if cmds.listRelatives(xform, shapes=True, type="mesh") and not RULE.match(short):
print("BAD NAME:", short)What transfers: the regex - literally the same line in all three, which is the whole argument for learning regex once. Note Unreal never loads an asset here: names live in the registry, so this validates a 50,000-asset project in seconds. Write the regex once, wire it into a pre-submit hook, and enforcement stops being a code-review chore.
import maya.cmds as cmds
for mesh in cmds.ls(type="mesh", noIntermediate=True, long=True):
uv_count = cmds.polyEvaluate(mesh, uvcoord=True)
if not uv_count:
print("NO UVs:", mesh)import maya.cmds as cmds
obj = cmds.ls(selection=True)[0]
if not cmds.attributeQuery("lodGroup", node=obj, exists=True):
cmds.addAttr(obj, longName="lodGroup", dataType="string")
cmds.setAttr(obj + ".lodGroup", "prop_small", type="string")
print(cmds.getAttr(obj + ".lodGroup"))What transfers: metadata is the connective tissue of pipelines - author it at the source, read it at the destination, and suddenly your importer knows things no filename could carry. The three-API chain above (Blender property -> FBX -> Unreal tag) is a complete mini-pipeline.
import maya.cmds as cmds
if cmds.menu("taMenu", exists=True):
cmds.deleteUI("taMenu")
menu = cmds.menu("taMenu", label="TA Tools",
parent="MayaWindow", tearOff=True)
cmds.menuItem(label="Audit Scene",
command=lambda *_: print("auditing..."))What transfers: the lesson that a tool without a button doesn't exist. Blender's ceremony (operator classes, registration) looks heavy next to Maya's two-liner, but it buys you undo integration, search, and keymaps for free - each DCC's "extra work" usually pays for something.
I keep this page's mapping in my head as a hiring test for myself: if I can't sketch a task in all three columns, I don't understand the task yet - I've just memorized one API's incantation for it. The incantations rot every version bump. The columns don't.