Optimize VRChat PhysBones with Limits and Constraints
PhysBone limits, PhysBone colliders, and VRChat Constraints solve different problems. Use a limit to restrict a moving bone chain, a collider when the chain must react to a surface, and a Constraint when one transform must follow or aim at another transform.
This guide replaces the older Dynamic Bone and Unity Constraint workflow. Current VRChat avatars should use VRC Phys Bone and VRChat Constraints directly.
Define the motion you need, then use the least expensive component that produces it.
- Use a PhysBone limit when a fixed movement range prevents clipping.
- Add colliders only where the chain must react to contact.
- Use a VRChat Constraint for deliberate transform-following behaviour.
- Never make a Constraint and PhysBone affect the same GameObject.
- Compare component, collision-check, constraint-count, and constraint-depth metrics.
VRChat warns that this creates execution-order issues. If the hierarchy needs both systems, move the Constraint to the parent GameObject and keep the PhysBone on its own chain object.
Choose the Correct System
| Requirement | Use | Why |
|---|---|---|
| Keep hair away from the head within a predictable range | PhysBone Limit | Restricts the chain without repeated collision checks. |
| Make hair, clothing, or a tail react to a body surface | PhysBone Collider | Provides contact response where a fixed limit is insufficient. |
| Let a chain be touched, grabbed, or posed | PhysBone collision and interaction settings | Uses the PhysBone interaction system and player permissions. |
| Make a prop follow a hand, head, or other transform | VRChat Parent, Position, or Rotation Constraint | Copies deliberate transform motion rather than simulating physics. |
| Aim an object toward a source | VRChat Aim or Look At Constraint | Provides controlled directional alignment. |
| Hold an avatar prop in world space | VRChat Constraint Freeze To World | Locks the affected axes in world space while enabled. |
Do not add a Constraint merely to make a PhysBone chain feel stiffer. Adjust Pull, Spring, Stiffness, Gravity, Immobile, and the PhysBone limit first.
Start with the Bone Hierarchy
Component tuning cannot fully compensate for an unsuitable hierarchy. Inspect the moving chain before changing settings.
Check that:
- the PhysBone root begins at the intended first moving transform
- child bones follow a clear order along the moving object
- unused helper bones are excluded or removed
- branching chains are intentional
- the last bone has a child or a suitable Endpoint Position
- the chain does not overlap another PhysBone component
- no Constraint affects the same GameObject as the PhysBone
One PhysBone can affect its root and descendants. Use a shared root for related branches when it produces correct motion, but do not create a huge chain only to reduce the displayed component count.
Replace Collider Jobs with Limits
VRChat specifically recommends movement limits for cases such as keeping hair from clipping into the head because a limit is more performant than a collider.
Angle
Use Angle when the chain can move within a cone. It is a good fit for hair strands, ears, tails, and accessories that need a simple maximum swing.
Hinge
Use Hinge when motion should stay on one plane. It suits objects intended to bend forward and backward without rotating sideways.
Polar
Use Polar when pitch and yaw require different ranges. VRChat notes that Polar limits have a non-zero performance cost, so use Angle when similar pitch and yaw values would produce the same result.
To configure a limit:
- Select the PhysBone component.
- Enable its Scene view gizmos.
- Choose the simplest suitable Limit Type.
- Align the limit using its rotation controls.
- Set the maximum angle or pitch and yaw ranges.
- Enter play mode and move the avatar root through the full expected range.
The limit gizmo should describe the usable movement envelope. If it points in the wrong direction, adjust its rotation rather than compensating with excessive stiffness.
Reduce PhysBone Collider Work
A PhysBone collider is useful only when a chain must react to that surface. Remove broad collision networks built from habit.
Review each collider:
- Does it prevent a visible collision problem?
- Which PhysBone components list or accept it?
- How many transforms can it affect?
- Could a limit replace it?
- Can one correctly positioned collider replace several overlapping colliders?
- Is its sphere, capsule, or plane shape appropriate?
- Does it begin outside the PhysBone radius in the rest pose?
The SDK reports PhysBones Collision Check Count as the total number of PhysBone transforms that colliders can affect. A transform can be counted more than once when several colliders affect it.
Reducing collider components is helpful, but reducing the relationships between colliders and affected transforms is the more direct way to lower this metric.
Tune Motion Before Adding More Structure
Adjust related PhysBone properties in separate passes:
| Symptom | Settings to review first |
|---|---|
| Chain takes too long to return | Increase Pull or Stiffness; review Spring. |
| Chain oscillates continuously | Reduce Spring or increase stabilizing Pull and Stiffness. |
| Chain barely moves | Reduce Stiffness or Pull; review the movement limit. |
| Root movement creates excessive swing | Review Immobile and the component's Root Transform. |
| Chain falls in an unwanted direction | Review Gravity and the chain's rest orientation. |
| Chain stretches or compresses too much | Review Stretch Motion, Max Stretch, and Max Squish. |
Make one category of changes at a time. PhysBone values interact, so changing every field at once makes the cause of a motion problem difficult to identify.
Use VRChat Constraints on Avatars
VRChat Constraints are the supported replacement for Unity Constraints on avatars. Unity Constraints are automatically converted when the avatar loads, but using VRChat Constraints directly gives a more accurate editor preview and a more accurate constraint-depth calculation.
The available types are:
| Constraint | Behaviour |
|---|---|
| VRC Aim Constraint | Rotates a target so a configured axis aims toward its sources. |
| VRC Look At Constraint | Rotates a target so its positive Z axis faces its sources. |
| VRC Parent Constraint | Copies position and rotation from its sources. |
| VRC Position Constraint | Copies position from its sources. |
| VRC Rotation Constraint | Copies rotation from its sources. |
| VRC Scale Constraint | Copies scale from its sources. |
Use the SDK Builder's relevant Auto Fix when an avatar still contains Unity Constraints. Recheck any animation clips that controlled the converted components.
Configure a Constraint Safely
For a basic VRChat Constraint:
- Add the required VRC Constraint component to a GameObject that is not controlled by a PhysBone.
- Add the source transform or transforms.
- Set each source weight.
- Choose which position, rotation, or scale axes the constraint can affect.
- Use Activate to preserve the current offset, or Zero to reset the offset before activation.
- Confirm Is Active, the component checkbox, the GameObject, and Lock are enabled when the constraint should run.
- Test its behaviour in edit mode, play mode, and a local VRChat build.
The optional Target Transform lets a component affect another transform instead of the GameObject that holds the component. Do not point it at a GameObject that is also controlled by a PhysBone.
Keep Constraints Efficient
Avatar performance measures both constraint count and constraint depth.
- Constraint Count is the total number of Unity and VRChat Constraints, including disabled components.
- Constraint Depth is the longest chain of constraints that depend on one another.
Several independent constraint chains can be evaluated in parallel. A single long dependency chain must be evaluated in order, so shortening the longest chain can improve performance even when the total count stays the same.
To reduce constraint cost:
- Remove unused and duplicate constraints.
- Replace Unity Constraints with VRChat Constraints.
- Avoid making one constraint depend on another unless the dependency is required.
- Split unrelated behaviours into independent branches.
- Avoid changing source transform references at runtime.
- Animate source weights instead of swapping transform references where possible.
- Check the Builder after editing the hierarchy.
Disabled components still count toward Avatar Performance Rank, so disabling an unused constraint is not the same as removing it.
Unity Constraints are disabled on Android and iOS avatars. Use VRChat Constraints directly, and check the current mobile constraint-count and dependency-depth limits in the Avatar Performance Ranks documentation.
Freeze To World Is Not Disable
Freeze To World makes the constraint ignore its sources and actively keep the affected axes fixed in world space. Disabling the component stops constraint evaluation, but the transform still follows its parent hierarchy.
For a prop that must remain fully fixed:
- use a Parent Constraint when both position and rotation must remain fixed
- freeze every required axis
- enable Freeze To World through the intended avatar animation
- decide whether Rebake Offsets When Unfrozen should calculate a new source offset when the prop returns
Freeze To World captures the pose when it changes from disabled to enabled. Leaving it enabled by default is not a reliable way to place an object at a predetermined world position.
Test the Combined Hierarchy
Test PhysBones and Constraints together even when they are placed on separate GameObjects.
Check:
- the constrained parent moves before the PhysBone child simulates
- the PhysBone returns cleanly after fast avatar movement
- limits stay aligned as constrained parents rotate
- colliders remain outside the chain's rest pose
- Constraint source weights blend as intended
- Freeze To World releases and rebakes offsets correctly
- disabled states return transforms and bones to the intended position
- mobile builds retain the supported components
Use the SDK Builder for performance metrics and VRChat's Avatar Overlay for in-client PhysBone and Contact debugging.
Troubleshooting
The PhysBone jitters after I added a Constraint.
Confirm that the Constraint does not affect the same GameObject as the PhysBone. Move the Constraint to the parent GameObject, remove overlapping transform control, and test the hierarchy again.
The chain clips even with several colliders.
Check whether an Angle, Hinge, or Polar limit better describes the allowed movement. Then inspect the chain radius and remove colliders that overlap or do not affect the intended PhysBone.
The PhysBone limit points in the wrong direction.
Enable the PhysBone limit gizmo and adjust the limit rotation. Verify the bone's local orientation and Root Transform before compensating with Pull, Stiffness, or collider placement.
The VRChat Constraint does not move its target.
Confirm Is Active, the component, and its GameObject are enabled. Add a valid source with non-zero weight, then activate and lock the constraint so its at-rest and offset values stop recalculating.
The avatar's constraint depth is unexpectedly high.
Convert remaining Unity Constraints through the SDK Auto Fix, then inspect the longest chain of constraint dependencies. Independent branches do not add their depths together, but a sequential chain does.
Freeze To World still lets the prop move.
Check which axes are selected for the constraint. Freeze To World only fixes the axes the component is configured to affect; use a Parent Constraint and select all required position and rotation axes for a fully fixed prop.
The setup works on PC but not on the mobile avatar.
Confirm the avatar uses VRChat Constraints rather than Unity Constraints, then review the mobile PhysBone, collision-check, constraint-count, and constraint-depth limits in the current SDK Builder.
Optimization Checklist
- Every PhysBone, collider, and Constraint has a specific job.
- A movement limit replaces collision where contact response is unnecessary.
- Colliders affect only the required chains and transforms.
- No Constraint affects a GameObject controlled by a PhysBone.
- Avatar Constraints use VRChat components rather than Unity components.
- Unused disabled components are removed.
- Constraint dependencies are as short as the behaviour permits.
- Builder PhysBone and Constraint metrics meet the intended platform target.
- PC and mobile avatar variants have been tested separately.
Official References
- VRChat Creation: PhysBones
- VRChat Creation: Constraints
- VRChat Creation: Avatar Performance Ranks
- VRChat Creation: Allowed Avatar Components
- VRChat Creation: Debugging Avatar Components
- VRChat Creation: Android Content Limitations