You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maya控制器层级创建脚本报错:Cannot parent components or objects in the underworld

Fix for "Cannot parent components or objects in the underworld" Warning in Maya Python Script

Let's break down why you're seeing that warning and how to fix it quickly:

The Root Cause

The cmds.circle() command returns a list with two items: the transform node (the top-level object you see in the Outliner) and the underlying shape node (the actual curve geometry, which lives in Maya's "underworld"—the lower part of the DAG hierarchy).

In your original code, you're storing the entire list in firstCtrl and circleCtrl, then trying to parent groups to these lists. Maya interprets this as trying to parent to the shape node (since it's part of the list), which is not allowed—shape nodes can't be parent targets for transforms.

The Fix

Simply grab only the transform node from the cmds.circle() result by indexing [0]. Here's the corrected code:

import maya.cmds as cmds

def setZero(target):
    cmds.setAttr("%s.translateX" % target, 0)
    cmds.setAttr("%s.translateY" % target, 0)
    cmds.setAttr("%s.translateZ" % target, 0)
    cmds.setAttr("%s.rotateX" % target, 0)
    cmds.setAttr("%s.rotateY" % target, 0)
    cmds.setAttr("%s.rotateZ" % target, 0)

# Add a check to avoid errors if nothing is selected
selJoint = cmds.ls(selection=True, shortNames=True)
if not selJoint:
    cmds.warning("Please select at least one joint first!")
else:
    # Grab ONLY the transform node of the circle
    firstCtrl = cmds.circle(normal=(1,0,0))[0]
    firstGrp = cmds.group(firstCtrl)
    cmds.parent(firstGrp, selJoint[0])
    setZero(firstGrp)
    cmds.parent(firstGrp, world=True)

    # Loop through remaining joints (skip first one directly)
    for joint in selJoint[1:]:
        # Again, grab the transform node of the new circle
        circleCtrl = cmds.circle(normal=(1,0,0))[0]
        offsetGrp = cmds.group(circleCtrl)
        cmds.parent(offsetGrp, joint)
        setZero(offsetGrp)
        cmds.parent(offsetGrp, world=True)
        cmds.parent(offsetGrp, firstCtrl)
        
        # Update the parent target for the next iteration
        firstCtrl = circleCtrl

Extra Improvements

  • Added a check for empty selection to prevent index errors if no joints are selected.
  • Changed the loop to iterate over selJoint[1:] instead of checking if joint == selJoint[0] each time—cleaner and more efficient.
  • If you want to simplify the setZero function, you can use cmds.xform instead of multiple setAttr calls:
    def setZero(target):
        cmds.xform(target, translate=(0,0,0), rotate=(0,0,0), worldSpace=False)
    

This will eliminate the "underworld" warning entirely, since you're now parenting groups to valid transform nodes (the circle controllers) instead of shape components.

内容的提问来源于stack exchange,提问作者DaveTheDolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:27:56