Set Up a Two-Handed Avatar Prop with VRChat Constraints
Attach a prop to one tracked hand with a VRC Parent Constraint, then use an avatar animation to place the other hand on a support grip. This pattern works for tools, instruments, cameras, blasters, and other cosmetic avatar props that need a stable primary hand and a deliberate second-hand pose.
The older Unity 2018 Constraint workflow is no longer the right target. Current avatars should use VRChat Constraints directly so the editor preview, runtime behaviour, mobile support, and performance metrics match VRChat more closely.
Keep the prop under the avatar hierarchy, constrain it to one hand, and animate only the support arm and hand.
- Create a prop root and support-grip marker under the avatar.
- Use a VRC Parent Constraint to follow the primary hand.
- Activate and lock the constraint while preserving the grip offset.
- Author a support-arm pose that meets the prop's grip marker.
- Use Tracking Control while the pose is active, then restore tracking on exit.
Animator Tracking Control switches a hand between VRChat IK tracking and the active animation. A rigid two-hand pose therefore overrides live tracking for the support hand while that state is active.
How the Setup Is Divided
| Part | Responsibility |
|---|---|
| Primary hand | Continues to follow the user's tracked controller or desktop IK. |
| VRC Parent Constraint | Moves and rotates the prop root as if it were a child of the primary hand. |
| Support grip marker | Shows where the second hand should meet the prop. |
| Support-arm animation | Poses the other arm and hand at the marker. |
| Animator Tracking Control | Lets the animation control the support hand while the two-hand state is active. |
| FX controller | Enables the prop and animates non-transform component properties such as constraint weights. |
Do not add another Animator component to the avatar. VRChat combines the controllers assigned to the Avatar Descriptor's Playable Layers.
Prepare the Prop Hierarchy
Create a small hierarchy beneath the avatar root:
Avatar
└── PropSystem
└── PropRoot
├── PropMesh
└── SupportGrip
- PropSystem keeps the feature together and provides space for helper components.
- PropRoot is the transform moved by the Parent Constraint.
- PropMesh contains the visible mesh and materials.
- SupportGrip is an empty transform placed where the support palm should sit.
Align the prop's local forward and up directions before configuring the constraint. Place the SupportGrip at the intended palm centre and rotate it to match the desired wrist orientation.
Keep the visible mesh as a child of PropRoot. This lets you adjust mesh alignment without changing the constraint target or animation paths.
Position the Primary Grip
Choose one humanoid hand as the primary source, such as RightHand.
- In Unity's Scene view, move
PropRootinto the intended primary-hand grip. - Check the handle position from the front, side, and hand-local views.
- Confirm the prop does not intersect the palm or fingers in the avatar's default hand pose.
- Keep the avatar and prop at their normal scale while setting the offset.
The support-hand animation will be authored around this primary alignment, so finish the primary grip before creating the pose.
Add the VRC Parent Constraint
Add VRC Parent Constraint to PropRoot.
- Add the primary hand bone to Sources.
- Set its source Weight to
1. - Keep the constraint's overall Weight at
1for the equipped state. - Enable the required position and rotation axes.
- Select Activate to preserve the prop's current offset from the hand.
- Confirm Is Active and Lock are enabled.
A Parent Constraint stores position and rotation offsets for each source. Activate preserves the current grip offset, while Zero resets the offsets. For a prop that has already been positioned in the hand, Activate is normally the intended choice.
Enter play mode and rotate the avatar's hand. The prop should follow without snapping to a different position.
Create the Support-Hand Pose
Create an animation clip for the support arm after the constrained prop is aligned.
- Make a duplicate test scene or animation workspace.
- Put the prop in its equipped position.
- Rotate the support shoulder, upper arm, lower arm, hand, and fingers until the palm matches
SupportGrip. - Record only the required humanoid muscles or transforms.
- Check elbow direction and wrist rotation from several angles.
- Save the pose as a dedicated clip.
Use an Avatar Mask so the animation affects only the required arm and hand. The Gesture Playable Layer is designed for animations affecting individual body parts while the rest of the avatar keeps its underlying motion. Use Action instead when the state intentionally overrides a broader body pose.
Avoid recording the prop's transform in the support-arm clip. The Parent Constraint already controls the prop, and recording both systems can create competing motion.
Hand Control and IK
Add VRC Animator Tracking Control to the animator state that plays the two-handed pose:
- keep the primary hand set to Tracking
- set the support hand to Animation
- leave unrelated tracking points at No Change
When leaving the pose, enter a state that returns the support hand to Tracking. Tracking Control persists until another state changes it, so the reset state is required.
This choice has a direct tradeoff:
| Support hand mode | Result |
|---|---|
| Tracking | Follows the user's controller or IK but can move away from the prop grip. |
| Animation | Holds the authored two-hand pose but ignores live hand tracking. |
Test the blend into and out of the pose. An instant switch can look abrupt, while a long blend can make the hand slide visibly through the prop.
Organize the Playable Layers
Use the Avatar Descriptor's existing Playable Layers:
- Gesture: local support-arm and hand transform pose
- Action: a full or broad body override when required
- FX: prop visibility, material changes, and constraint component properties
Do not animate humanoid arm transforms in FX. VRChat documents FX as the layer for non-transform effects, while Gesture and Action are designed for transform animation.
If a prop GameObject has both a transform animation and an effect component, split those responsibilities across parent and child GameObjects so the Avatar Masks do not conflict.
Add an Equip Toggle
A basic equipped state normally controls:
- the visible
PropMeshGameObject - the Parent Constraint's overall weight or active state
- the support-hand Gesture or Action state
- Tracking Control for the support hand
The unequipped state should:
- hide the prop mesh
- stop the support-hand pose
- return the support hand to Tracking
- leave the prop root in a predictable rest state
Use an Expression Menu toggle and expression parameter when the wearer should control this state. Keep the parameter name, animator transitions, and default value consistent across the menu, parameters asset, and controller.
Optional Left-Hand and Right-Hand Modes
A Parent Constraint can contain separate left-hand and right-hand sources, each with its own offset.
To support handedness switching:
- Position the prop for the right-hand grip and activate the right-hand source offset.
- Configure the left-hand source with its own grip offset.
- Create states where only one source has weight
1and the other has weight0. - Create separate support-arm poses for each handedness.
- Switch Tracking Control so only the current support hand is animation-driven.
VRChat recommends animating existing source weights instead of changing transform references at runtime. Confirm that each state has one clear primary source; blending two hand sources simultaneously can pull the prop between them.
Keep the Constraint Hierarchy Safe
Avoid these conflicts:
- a PhysBone and Constraint affecting the same GameObject
- two constraints writing incompatible motion to the same target
- an animation clip recording
PropRootwhile its Parent Constraint is active - a support-hand animation playing while that hand remains set to Tracking
- a second Animator component duplicating the Avatar Descriptor's playable-layer work
If the prop contains PhysBone decorations, put the PhysBone component on a child chain rather than on PropRoot. VRChat warns against a Constraint and PhysBone affecting the same GameObject because of execution-order issues.
Performance and Mobile Support
The SDK counts every Constraint on an avatar, including disabled components. It also measures Constraint Depth, the longest chain of Constraint dependencies.
Keep this feature compact:
- use one Parent Constraint for the prop root
- avoid sequential helper constraints when a direct source works
- remove abandoned test constraints
- use VRChat Constraints instead of Unity Constraints
- keep decorative PhysBones separate and minimal
- review both Constraint Count and Constraint Depth in the Builder
Unity Constraints are disabled on Android and iOS avatars. VRChat Constraints are the supported cross-platform choice, subject to the current mobile performance limits.
Test the Two-Handed Prop
Use the SDK's local avatar test build and check:
- desktop mode with keyboard and mouse
- three-point VR tracking
- full-body tracking if the avatar is intended for it
- both left- and right-handed states when included
- equip and unequip transitions
- support-hand Tracking Control reset
- prop visibility for local and remote users
- gesture input and Expression Menu input
- Android or iOS builds when supported
Watch the shoulders and elbows as well as the hands. A pose that aligns perfectly in the Unity preview can still look strained with different player proportions or tracking modes.
Troubleshooting
The prop snaps to the hand with the wrong offset.
Place PropRoot in the intended grip before activating the Parent Constraint, then use Activate to preserve that offset. Zero clears the stored offset and is not appropriate when the prop has already been aligned.
The support hand keeps following my controller.
Add Animator Tracking Control to the active pose state and set the support hand to Animation. Confirm the state is actually active and that a later state is not immediately returning the hand to Tracking.
The support hand remains frozen after unequipping.
Tracking Control persists. Add it to the exit or idle state and explicitly return the support hand to Tracking when the two-handed pose ends.
The arm pose works but the prop does not appear.
Check the FX state that controls PropMesh visibility, the toggle parameter, and the animator transition conditions. Keep prop visibility separate from the Gesture or Action transform pose.
The prop drifts between the left and right hands.
Inspect the Parent Constraint source weights. The active primary hand should normally have weight 1 while the other source has weight 0; unintended blending makes the target follow a weighted position between sources.
The Constraint works in edit mode but not in VRChat.
Confirm the avatar uses VRC Parent Constraint, not an unconverted Unity Constraint. Check Is Active, Lock, source references, component state, and the SDK Builder validations before creating another local test build.
The hand or elbow bends unnaturally in VR.
Adjust the authored support-arm pose and its Avatar Mask, then test with the intended tracking modes. A single fixed pose cannot perfectly match every avatar proportion and player tracking configuration.
A PhysBone decoration jitters on the constrained prop.
Keep the Parent Constraint on PropRoot and move the PhysBone to a child chain. Confirm that no Constraint targets the same GameObject as the PhysBone component.
Setup Checklist
- The prop has a dedicated root, mesh child, and support-grip marker.
- A VRC Parent Constraint follows one primary hand.
- Activate preserves the intended grip offset.
- The support animation records only the required arm and hand.
- Gesture or Action uses an appropriate Avatar Mask.
- Tracking Control switches the support hand to Animation and back to Tracking.
- FX handles prop visibility and component properties.
- Left/right source weights do not blend unintentionally.
- No PhysBone and Constraint affect the same GameObject.
- Constraint Count and Depth meet the intended platform target.
- Desktop, VR, full-body, and mobile modes are tested as applicable.
Official References
- VRChat Creation: Constraints
- VRChat Creation: Parent Constraint
- VRChat Creation: Playable Layers
- VRChat Creation: State Behaviors and Tracking Control
- VRChat Creation: Avatar Performance Ranks
- VRChat Creation: Android Content Limitations
- VRChat Creation: Allowed Avatar Components