Create a World-Fixed Prop with VRChat Constraints

A world-fixed avatar prop follows an avatar anchor until the wearer enables Freeze To World. The constraint then ignores its source and keeps the prop at its current world-space position and rotation until the wearer releases it.

Use VRChat's VRCParentConstraint for this workflow. VRChat recommends its own constraint components for avatars, and a Parent Constraint can freeze both position and rotation.

Follow, Place, and Return

One Parent Constraint follows a hand anchor, while a reversible FX toggle animates Freeze To World.

  1. Create a hand anchor and a separate constrained prop root.
  2. Record Follow and World-Fixed clips that change only Freeze To World.
  3. Drive both states with one Bool Toggle and test placement from a private upload.

Video Walkthrough

Video creator: DedZedOffishal

Use the walkthrough for the Unity interaction. Use the hierarchy, constraint settings, and reset checks below for the current VRChat Constraint implementation.

Freeze To World is not the same as disabling a constraint

A disabled constraint stops updating its target in local space, so the target still moves with the avatar hierarchy. Freeze To World keeps the constraint active and updates the target so its world-space pose stays fixed.

What This Feature Does

Toggle state Constraint state Prop behavior
Off Freeze To World disabled Prop follows the configured hand anchor
On Freeze To World enabled Prop stays at the world-space pose captured when the toggle changed
Off again Freeze To World disabled Prop follows its source and original offset again

This is still part of the avatar. It is not a world pickup, does not become a persistent world object, and disappears when the avatar is no longer present.

What You Need

  • A working avatar upload.
  • A visible prop already positioned near the hand or another avatar anchor.
  • An Expressions Menu and Expression Parameters asset assigned to the avatar.
  • A custom FX Animator Controller assigned to the avatar descriptor.
  • The VRChat SDK's VRCParentConstraint.
  • A backup or version-control checkpoint before changing the hierarchy.

Complete Create an Object Toggle first if the prop cannot yet be shown and hidden reliably.

1. Build the Prop Hierarchy

Keep the follow source and constrained target separate:

Avatar
├─ Armature
│  └─ ...RightHand
│     └─ WorldProp_FollowAnchor
└─ WorldProp_Root
   └─ WorldProp_Visual

Follow Anchor

Create WorldProp_FollowAnchor under the hand bone. Position and rotate it where the prop should sit while carried.

Constrained Root

Create WorldProp_Root under the avatar root, not under the hand. Put the mesh, renderer, and optional interaction components under WorldProp_Visual.

This separation gives the constraint a source to follow and a target it can hold in world space.

2. Add the VRC Parent Constraint

Add a VRCParentConstraint to WorldProp_Root.

Configure it as follows:

Setting Value
Is Active Enabled
Weight 1
Target Transform Empty, so the component controls its own transform
Source Transform WorldProp_FollowAnchor
Source Weight 1
Freeze Position Axes X, Y, and Z selected
Freeze Rotation Axes X, Y, and Z selected
Freeze To World Disabled by default
Rebake Offsets When Unfrozen Disabled for a return to the original hand offset

With the prop arranged where it should follow the hand, use the constraint's Activate utility. VRChat documents this utility as saving the current source offset, activating the constraint, and locking it.

Confirm:

  • Is Active is enabled.
  • Lock is enabled.
  • The component itself is enabled.
  • WorldProp_Root is active.
  • Moving the hand anchor makes the prop follow.
Freeze every required axis

Freeze To World only affects axes selected in the constraint settings. Select all position and rotation axes when the prop must remain completely fixed.

3. Decide the Return Behavior

The Rebake Offsets When Unfrozen option changes what happens when the prop leaves its world-fixed state.

Setting Result when Freeze To World turns off
Disabled Constraint uses its original stored offset and returns to the hand anchor pose
Enabled Constraint recalculates its offset relative to the source at the moment it unfreezes

Leave it disabled for a simple place-and-return prop. Enable it only when retaining the newly calculated source offset is intentional and tested.

4. Record the Constraint Clips

Create two Animation Clips:

WorldProp_Follow.anim
WorldProp_Frozen.anim

Record only the Parent Constraint's Freeze To World property:

Clip Freeze To World
WorldProp_Follow Disabled
WorldProp_Frozen Enabled

Do not record:

  • The constraint component enabled state.
  • Is Active.
  • The target or source transform references.
  • The prop transform.
  • Unrelated renderer or object states.

VRChat advises against changing constraint transform references at runtime. Keep the source and target fixed and animate only Freeze To World.

5. Add the Bool Parameter

Add the same parameter to the Expression Parameters asset and FX Animator Controller:

Name: Props/WorldLock
Type: Bool
Default: false

Recommended options:

Option Recommendation Reason
Saved Disabled A saved frozen state can activate immediately when the avatar loads
Synced Enabled when remote players need the state Other clients receive the same avatar animation parameter

VRChat warns that having Freeze To World enabled by default only freezes the transform where it happens to load; it does not guarantee a specific world-space placement. Keep the uploaded default unfrozen.

6. Build the FX Layer

Create an FX layer named Prop - World Lock and set its weight to 1.

State Motion Role
Follow Hand WorldProp_Follow Orange default state
Freeze In World WorldProp_Frozen Captures and maintains the placed pose

Add both transitions:

Transition Condition
Follow Hand → Freeze In World Props/WorldLock is true
Freeze In World → Follow Hand Props/WorldLock is false

Disable Has Exit Time and set transition duration to 0 in both directions.

The reverse transition is the reset path. Do not build a frozen state that cannot return to the following state.

7. Add the Expressions Toggle

In the Expressions Menu:

  1. Add a control named Place Prop.
  2. Set its type to Toggle.
  3. Assign Props/WorldLock.
  4. Confirm the Avatar Descriptor references the edited menu and Expression Parameters asset.
  5. Confirm the descriptor's FX playable layer uses the controller you edited.

8. Add Visibility Without Stopping the Constraint

After placement works, add a separate visibility control if needed.

Keep WorldProp_Root active so its constraint continues to evaluate. Toggle a visual child or its renderer instead:

WorldProp_Root            ← remains active
└─ WorldProp_Visual       ← visibility toggle targets this child

Deactivating the GameObject that contains the constraint stops the constraint from running. Separating the visual child prevents the hide control from silently disabling the placement system.

Recommended reset sequence:

  1. Turn off Place Prop so the root follows the hand again.
  2. Hide WorldProp_Visual.
  3. Show the visual before placing it again.

9. Remote and Platform Behavior

A synced Bool communicates avatar animation state. Treat the result as a constrained avatar prop, not as a networked world pickup with authoritative world coordinates.

Test with another player because every client renders the avatar and evaluates its constraints.

For mobile avatars:

  • Use VRChat Constraints rather than Unity Constraints.
  • Keep the same parameter position and Bool type across platform versions.
  • Use mobile-supported materials and components on the prop.
  • Check current constraint count and depth in the SDK performance report.

VRChat's Android content documentation disables Unity constraints on mobile avatars and directs creators to use VRChat Constraints.

Test Matrix

Test a private upload before publishing the avatar.

Test Expected result
Avatar loads Prop follows its anchor; it is not frozen
Hand moves before placement Prop maintains the configured offset
Place Prop turns on Prop freezes at its current position and rotation
Avatar walks away Prop stays at the captured world-space pose
Avatar rotates Prop remains fixed
Place Prop turns off Prop returns to its hand-following offset
Toggle repeats several times Every placement and reset remains reversible
Visual child hides Constraint root remains active
Avatar reloads Unsaved parameter returns to following state
Remote player observes a synced toggle Remote avatar shows the same follow/frozen state
PC avatar is viewed Constraint and materials behave correctly
Mobile avatar is viewed VRC constraint remains valid and mobile content is supported

Troubleshooting

Help! The prop still follows my avatar after I place it.

Confirm the Frozen clip records Freeze To World rather than disabling the component. Then verify all position and rotation axes are selected, Is Active is enabled, and the constraint is locked.

Help! The prop jumps when the avatar loads.

Keep Freeze To World disabled in the component and Expression Parameter defaults. The Follow Hand state should be the orange default state, and Saved should be disabled while testing.

Help! The prop returns to the wrong hand position.

Reposition the follow anchor, arrange the prop at the intended carried pose, and use Activate again to capture the offset. Leave Rebake Offsets When Unfrozen disabled for a return to that stored offset.

Help! Hiding and showing the prop breaks placement.

Do not deactivate the GameObject containing the constraint. Keep WorldProp_Root active and toggle only WorldProp_Visual or its renderer.

Help! The toggle changes but the constraint does not.

Check that the menu control, Expression Parameters asset, FX Bool, and transition conditions all use Props/WorldLock. Confirm the descriptor uses the assets you edited.

Help! Other players see the prop differently.

Enable Synced for the Bool and test with an observer after uploading. Remember that the feature synchronizes avatar animation state; it is not a world pickup with separate network ownership.

Help! The constraint works on PC but not on mobile.

Confirm the mobile avatar uses a VRCParentConstraint rather than a Unity constraint, stays within current mobile component limits, and uses supported prop materials and components.

Help! The SDK reports a worse constraint rating.

Review both constraint count and dependency depth. Disabled constraints still count, and VRChat reports depth more accurately when the avatar uses VRChat Constraints exclusively.

Official References

Related Avatar Guides

Topics: VRChat world-fixed prop, Freeze To World, VRC Parent Constraint, avatar props