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.
One Parent Constraint follows a hand anchor, while a reversible FX toggle animates Freeze To World.
- Create a hand anchor and a separate constrained prop root.
- Record Follow and World-Fixed clips that change only Freeze To World.
- 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.
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_Rootis active.- Moving the hand anchor makes the prop follow.
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:
- Add a control named
Place Prop. - Set its type to Toggle.
- Assign
Props/WorldLock. - Confirm the Avatar Descriptor references the edited menu and Expression Parameters asset.
- 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:
- Turn off
Place Propso the root follows the hand again. - Hide
WorldProp_Visual. - 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
Booltype 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
- VRChat Constraints
- VRChat Parent Constraint
- VRChat Expressions Menu and Controls
- VRChat Animator Parameters
- VRChat Avatar Performance Ranks
- VRChat Android Content Limitations
Related Avatar Guides
- Create an Object Toggle
- Save Avatar Toggle States
- Add PhysBones to an Avatar
- Toggle Avatar PhysBones
- VRChat Avatar Optimization Checklist
Topics: VRChat world-fixed prop, Freeze To World, VRC Parent Constraint, avatar props