name: vrchat-foot-heel-linkage description: Link Foot_Heel blendshape to wardrobe clothing states via animation clips in FX Controller Layer tags: [vrchat, unity, animation, foot-heel, wardrobe, blendshape, fx-controller]
VRChat Foot_Heel Blendshape Linkage via AnimationClips
Problem
When an avatar has multiple clothing sets with different heel heights (pumps/high heels vs sandals/flats), the Foot_Heel blendshape on Body_Base needs to change automatically when switching clothes via the wardrobe menu.
Manually setting Foot_Heel via blendshape slider only works for preview — for runtime behavior, it must be animation-driven.
Architecture (Option A: Modify Wardrobe Clips)
Use the wardrobe animation clips (already used for clothing m_IsActive control) to also set Foot_Heel blendshape value:
Layer 18 WardrobeCloth
├── Cloth_原皮.anim → Foot_Heel = 100 (high heel)
├── Cloth_露肩短裙.anim → Foot_Heel = 100 (high heel)
├── Cloth_休闲服.anim → Foot_Heel = 0 (flat)
└── Cloth_全脱.anim → Foot_Heel = 0 (flat)
Step-by-Step Implementation
eel = 0 (flat) └── Cloth_全脱.anim → Foot_Heel = 0 (flat)
## Step-by-Step Implementation### Quickest Approach (Option B: Dedicated Foot Layer)
Rather than modifying existing wardrobe clips (Option A — fragile if clips are regenerated), create a **dedicated high-priority Layer** that sets Foot_Heel based on Wardrobe_Int1:
**AnimationClips needed (2 total):**
- `FootHeel_Tiptoe.anim`: `Body_Base: blendShape.Foot_Heel = 100`
- `FootHeel_Flat.anim`: `Body_Base: blendShape.Foot_Heel = 0`
dy_Base: blendShape.Foot_Heel = 100`
- `FootHeel_Flat.anim`: `Body_Base: blendShape.Foot_Heel = 0`### Option A: Add BlendShape Curve to Existing AnimationClip
Modify each wardrobe clip directly:
```csharp
string clipPath = "Assets/Cazalis/Animation/Wardrobe/Cloth_原皮.anim";
AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
// Target: Body_Base SkinnedMeshRenderer
// Property: blendShape.Foot_Heel
EditorCurveBinding binding = new EditorCurveBinding();
binding.path = "Body_Base"; // GameObject name in hierarchy
binding.propertyName = "blendShape.Foot_Heel";
binding.type = typeof(SkinnedMeshRenderer);
AnimationCurve curve = AnimationCurve.Constant(0, 0, 100f); // single key at t=0
AnimationUtility.SetEditorCurve(clip, binding, curve);
EditorUtility.SetDirty(clip);
AssetDatabase.SaveAssets();
Key points:
- Single key at t=0 (constant curve) is sufficient — no interpolation needed
- Body_Base is the SkinnedMeshRenderer name, must match the actual hierarchy
- Property name is blendShape.Foot_Heel (case-sensitive)
- Alternative path may be Cazalis zigai/Body_Base if Body_Base is not root
- Body_Base has 92 blendshapes on Cazalis zigai
2. Verify Clip Contents
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
{
Debug.Log($"Path: {binding.path}, Prop: {binding.propertyName}");
}
Each State in Layer 18 (WardrobeCloth) needs transitions to all other States, conditioned on Wardrobe_Int1 parameter:
int[] stateIndices = {0, 1, 2, 3, 4}; // Idle, 原皮, 露肩短裙, 休闲服, 全脱
foreach (int srcIdx in stateIndices)
{
foreach (int dstIdx in stateIndices)
{
if (srcIdx == dstIdx) continue;
var transition = states[srcIdx].AddTransition(states[dstIdx]);
transition.hasExitTime = false;
transition.duration = 0;
transition.conditions = new AnimatorCondition[]
{
new AnimatorCondition
{
parameter = "Wardrobe_Int1",
mode = AnimatorConditionMode.Equals,
threshold = dstIdx - 1 // 原皮=0, 露肩短裙=1, 休闲服=2, 全脱=3
}
};
}
}
4. Verify Transitions in Animator Window
Open Window → Animation → Animator (Ctrl+6), select Layer 18 WardrobeCloth:
- Each State should have arrows to all other States
- Click an arrow → Inspector should show condition: Wardrobe_Int1 Equals X
Verification
- Each wardrobe clip has
blendShape.Foot_Heelcurve - High-heel clothes → Foot_Heel=100
- Flat clothes → Foot_Heel=0
- Naked → Foot_Heel=0
- Layer 18 Transitions connected with Wardrobe_Int1 conditions
- Test in VRChat: switch clothes, observe foot/ankle pose changes with Wardrobe_Int1 conditions
-
Test in VRChat: switch clothes, observe foot/ankle pose changes## Pitfalls
-
Cazalis zigai Body_Base path: The path for animation binding is just
Body_Base(child of rootCazalis zigai). Body_Base has 92 blendshapes total. - Foot_Heel naming: Exact blendShape name is
Foot_Heel(notFoot_Heel_L/R). There are also related blendshapes:Foot_Highheel(currently unused),Shrink_Ankle/L/R,Shrink_Foot/L/R,Shrink_Toe/L/R. - Wardrobe_Int1 mapping: User's setup maps Int values to clothing states. Flat-shoe states (休闲服/全脱) = 2/3, tiptoe states = 0/1.
- Option B cleanest: Dedicated FootHeight Layer avoids touching existing wardrobe clips, cleaner architecture.
- MCP Code transitions may not persist: C# code that modifies AnimatorController transitions may work in editor session but not save to disk. Always verify in Animator window after running code.