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

Maya脚本重复运行时如何避免Shader/Shading Engine被命名为MAT1、MATSG1?

问题解决:Maya肢体Shader统一与重命名重复运行增量问题

问题核心

脚本首次运行能正确为成对肢体分配同名Shader并重命名,但重复运行时Shader会出现Hand_MAT1、Hand_MATSG1这类带增量的命名;尝试删除现有Shader时误删网格信息。

问题原因

  1. 重命名未检查目标名称是否存在:重复运行时,目标Shader/着色组名称已存在,Maya自动添加增量后缀避免命名冲突。
  2. 删除Shader操作错误:直接删除Shader未先断开与网格的连接,导致连带删除了关联的形状节点(或误选了网格对象)。
  3. 现有逻辑未复用已存在的目标Shader:脚本每次运行都尝试重命名旧Shader,而非直接使用已存在的正确命名Shader。

修正后的脚本

import maya.cmds as cmds

def get_or_create_body_shader(body_part):
    """获取或创建对应肢体的标准命名Shader与着色组"""
    shader_name = f"{body_part}_MAT"
    sg_name = f"{body_part}_MATSG"
    
    # 检查Shader是否已存在
    if cmds.objExists(shader_name):
        shader = shader_name
    else:
        # 创建Lambert Shader(可根据需求替换为其他类型,比如aiStandardSurface)
        shader = cmds.shadingNode("lambert", asShader=True, name=shader_name)
    
    # 检查着色组是否已存在
    if cmds.objExists(sg_name):
        sg = sg_name
    else:
        sg = cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=sg_name)
        # 连接Shader到着色组
        cmds.connectAttr(f"{shader}.outColor", f"{sg}.surfaceShader", force=True)
    
    return sg, shader

# 收集符合条件的肢体变换节点
selected_transforms = []
shading_engines = {}
target_body_parts = ["Arm", "Leg", "Hand"]

for transform in cmds.ls(transforms=True):
    if ("LT_" in transform or "RT_" in transform) and any(part in transform for part in target_body_parts):
        shapes = cmds.listRelatives(transform, shapes=True, noIntermediate=True)
        if shapes:
            # 获取当前形状节点的着色组
            sgs = cmds.listConnections(shapes[0], type="shadingEngine")
            if sgs:
                sg_name = sgs[0]
                # 获取关联的Shader名称
                shader_name = cmds.connectionInfo(f"{sg_name}.surfaceShader", sourceFromDestination=True).split(".")[0]
                shading_engines[transform] = [sg_name, shader_name]
                selected_transforms.append(transform)

# 统一成对肢体的Shader
for transform in selected_transforms:
    # 获取成对的肢体节点(LT/RT互换)
    paired_transform = transform.replace("LT_", "RT_") if "LT_" in transform else transform.replace("RT_", "LT_")
    if paired_transform not in shading_engines:
        continue
    
    # 提取肢体类型(Arm/Leg/Hand)
    body_part = transform.split("_")[1]
    # 获取或创建标准Shader与着色组
    target_sg, target_shader = get_or_create_body_shader(body_part)
    
    # 将当前变换与成对变换的形状节点都指定到目标着色组
    for t in [transform, paired_transform]:
        shapes = cmds.listRelatives(t, shapes=True, noIntermediate=True)
        if shapes:
            cmds.sets(shapes[0], edit=True, forceElement=target_sg)
    
    # 删除旧的Shader与着色组(如果不是目标对象)
    old_sg, old_shader = shading_engines[transform]
    if old_sg != target_sg and cmds.objExists(old_sg):
        # 先检查着色组是否还有其他连接,避免误删
        members = cmds.sets(old_sg, query=True)
        if not members:
            cmds.delete(old_sg)
    if old_shader != target_shader and cmds.objExists(old_shader):
        # 检查Shader是否还有其他连接
        connections = cmds.listConnections(old_shader, source=False, destination=True)
        if not connections:
            cmds.delete(old_shader)

# 清理可能残留的重复Shader(可选)
for part in target_body_parts:
    # 删除带增量的冗余Shader
    for shader in cmds.ls(f"{part}_MAT*"):
        if shader != f"{part}_MAT" and not cmds.listConnections(shader):
            cmds.delete(shader)
    # 删除带增量的冗余着色组
    for sg in cmds.ls(f"{part}_MATSG*"):
        if sg != f"{part}_MATSG" and not cmds.sets(sg, query=True):
            cmds.delete(sg)

关键修改点

  • 新增get_or_create_body_shader函数:先检查目标名称的Shader/着色组是否已存在,存在则直接复用,不存在才创建,从根源避免增量命名问题
  • 统一Shader分配逻辑:直接将成对肢体的形状节点指定到目标着色组,不再依赖原Shader的重命名操作
  • 安全删除旧Shader:删除前检查旧Shader/着色组是否还有其他关联对象,只有无关联时才删除,彻底避免误删网格相关信息
  • 清理冗余增量对象:自动删除带增量后缀的冗余Shader与着色组,保持场景命名整洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:15:35