Ben Traje
← Back to rigging

How to Rivet Locked Objects to Vertices in Autodesk Maya Using Python

25 Aug 26 (2mo ago)

Attaching accessories, props, or control locators to deforming geometry is a core task in 3D rigging. While traditional MEL rivets often require two intersecting edges, Autodesk Maya's modern pointOnPolyConstraint allows you to snap and pin transforms directly to a single vertex.

When working with constrained rigs or downstream assets, target objects often have locked or hidden translation and rotation channels. Running a constraint script without unlocking these channels causes errors. Below is a streamlined Python solution that handles attribute unlocking and riveting in a single pass.

The Challenge: Locked Transforms in Constraints

Applying a constraint to a transform with locked attributes causes Maya's execution to fail. To automate the process reliably:

  1. Verify the target object exists in the scene.
  2. Iterate through translation (tx, ty, tz) and rotation (rx, ry, rz) attributes to set lock=False and keyable=True.
  3. Apply cmds.pointOnPolyConstraint() to link the target transform directly to the selected vertex.

Python Solution

Run this script inside Maya's Script Editor (Python tab):

import maya.cmds as cmds

def unlock_and_rivet(mesh_vtx: str, target_transform: str, maintain_offset: bool = False):
    """
    Unlocks transformation attributes and pins an object to a target vertex.
    """
    # Verify object existence
    if not cmds.objExists(target_transform):
        cmds.error(f"Target '{target_transform}' does not exist in the scene.")
        return

    # Unlock and unhide translation and rotation channels
    transform_attrs = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz']
    for attr in transform_attrs:
        full_attr = f"{target_transform}.{attr}"
        if cmds.objExists(full_attr):
            cmds.setAttr(full_attr, lock=False, keyable=True)

    # Apply the pointOnPolyConstraint
    constraint = cmds.pointOnPolyConstraint(
        mesh_vtx,
        target_transform,
        maintainOffset=maintain_offset
    )

    print(f"Successfully unlocked and riveted '{target_transform}' to '{mesh_vtx}'.")
    return constraint


# Example Execution
vertex_path = "RabbitZ_MainBody.vtx[2397]"
target_node = "bottle_C_C0_ik_cns"

unlock_and_rivet(vertex_path, target_node)

Key Advantages of pointOnPolyConstraint

  • Clean Node Graph: Avoids creating auxiliary curves, lofts, or extra DAG nodes required by legacy MEL rivet scripts.
  • Direct Deform Tracking: Moves and rotates synchronously with skinCluster, blendShape, and lattice deformations.
  • Offset Control: Toggle maintain_offset=True if you need the prop to preserve its original position relative to the vertex instead of snapping to it.