Swap Avatar Materials from the VRChat Expressions Menu
A material swap replaces the material assigned to one renderer slot. Use it for two complete, fixed appearances such as a default jacket and an alternate jacket, a matte and emissive version, or two authored texture sets.
The menu changes a Bool parameter. The FX Animator selects the default or alternate Animation Clip, and each clip holds one material reference in the same renderer slot.
Bind one renderer slot to a default material and an alternate material through two reversible FX states.
- Identify the renderer and exact material slot index.
- Record one clip for each material without capturing unrelated properties.
- Connect both clips to a Bool Toggle and test every supported platform version.
Avatar Performance Rank counts material slots on Renderer components. Replacing the material assigned to one existing slot does not create another slot, but every platform build still needs suitable materials, textures, and shaders for the appearances it can display.
Video Walkthrough
Use DedZedOffishal's video for the Unity demonstration and the renderer-slot checklist below while building the swap.
Creator: DedZedOffishal
Video: Material Swap | VRC Avatars for Dummies
Use a Swap for Fixed Appearances
| Intended control | Implementation |
|---|---|
| Default or alternate material | Bool material swap |
| Several named material presets | Int states or a preset menu |
| Continuous hue value | Float animation or Radial Puppet |
| Show or hide the entire mesh | Object toggle |
| Choose exactly one outfit | Exclusive parameter logic |
A two-state swap is most useful when each material has a deliberately authored combination of textures and shader settings.
Identify the Renderer Slot
Select the target Mesh Renderer or Skinned Mesh Renderer and inspect its Materials list:
Body (Skinned Mesh Renderer)
├── Element 0: Skin_Default
├── Element 1: Eyes_Default
└── Element 2: Jacket_Default ← swap this slot
Write down:
| Field | Example |
|---|---|
| Renderer path | Avatar/Body |
| Renderer type | Skinned Mesh Renderer |
| Slot index | Element 2 |
| Default material | Jacket_Default |
| Alternate material | Jacket_Alt |
The index matters. Recording a material in Element 1 when the jacket is Element 2 changes the wrong submesh.
Prepare Both Materials
Create or assign the two material assets before recording:
| Material | Purpose |
|---|---|
Jacket_Default |
Uploaded default appearance |
Jacket_Alt |
Alternate menu-selected appearance |
Confirm each material directly on the renderer:
- Assign
Jacket_Defaultto the target slot and inspect the avatar. - Assign
Jacket_Altto the same slot and inspect the avatar again. - Restore the material that should be active in the uploaded default.
Check the full visible result, including texture assignment, surface mode, culling, and any renderer-specific behavior supplied by the selected shader.
Record the Material Clips
Create:
Jacket_Default.animJacket_Alt.anim
Select the avatar root before opening Unity's Animation window. This keeps the material binding relative to the Animator that will play the FX controller.
Record only the target renderer slot:
| Clip | Element 2 material |
|---|---|
Jacket_Default.anim |
Jacket_Default |
Jacket_Alt.anim |
Jacket_Alt |
After recording, inspect both clips and remove unintended bindings. Neither clip should contain accidental Transform, GameObject active-state, blend shape, or unrelated material-slot keys.
Renaming or re-parenting the renderer can break the recorded path. Reordering the renderer's Materials list can make the same binding affect a different submesh. Verify both clips after either hierarchy or slot-order changes.
Create the FX State Machine
VRChat assigns material swaps and other non-transform visual effects to the FX Playable Layer.
Add this Bool to the FX Animator Controller:
| Field | Value |
|---|---|
| Name | Appearance/JacketAlt |
| Type | Bool |
| Default | False |
Create a dedicated Animator layer:
Entry
└── Jacket Default ───────────► Jacket Alternate
Appearance/JacketAlt=true
Jacket Alternate ─────────► Jacket Default
Appearance/JacketAlt=false
Assign the clips:
| State | Motion |
|---|---|
| Jacket Default | Jacket_Default.anim |
| Jacket Alternate | Jacket_Alt.anim |
Set Jacket Default as the layer's default state for this off-by-default example.
Configure Both Transitions
Default → Alternate
Has Exit Time: disabled
Transition Duration: 0
Condition: Appearance/JacketAlt == true
Alternate → Default
Has Exit Time: disabled
Transition Duration: 0
Condition: Appearance/JacketAlt == false
A material reference changes discretely, so the transition does not need a blend. Both transitions are required so the Animator can respond whenever the Bool changes.
Add the Expression Parameter
In the VRC Expression Parameters asset assigned to the avatar, add:
| Field | Value |
|---|---|
| Name | Appearance/JacketAlt |
| Type | Bool |
| Default | False |
| Saved | On when the wearer should retain the selection |
| Synced | On when other users should receive the selected state |
The name and Bool type must match the FX Animator parameter. A synced Bool uses one bit of synchronized custom-parameter memory.
Add the Expressions Menu Toggle
In the Expressions Menu assigned to the avatar, add:
| Menu field | Value |
|---|---|
| Name | Alternate Jacket |
| Type | Toggle |
| Parameter | Appearance/JacketAlt |
Activating the Toggle sets the Bool true; turning it off resets the Bool to false. Button and Toggle controls use VRChat's Playable synchronization mode.
Assign the Avatar Descriptor Assets
Select the avatar root and confirm:
| Descriptor section | Assignment |
|---|---|
| Expressions → Menu | Menu containing Alternate Jacket |
| Expressions → Parameters | Asset containing Appearance/JacketAlt |
| Playable Layers → FX | Animator Controller containing the material-swap layer |
Use an Animation Controller in the FX slot and do not reuse the same controller in multiple Playable Layers.
Align the Default Material
For the default jacket to load first:
| Location | Expected value |
|---|---|
| Renderer Element 2 in the prefab | Jacket_Default |
| Expression Parameter Default | False |
| FX Animator Bool default | False |
| FX layer default state | Jacket Default |
If Saved is enabled, a stored wearer selection can override the Default when the avatar loads. Reset the avatar before judging a changed default material.
Configure PC and Mobile Versions
PC and mobile versions may require different material assets. Keep the behavior equivalent:
| PC version | Mobile version |
|---|---|
Jacket_Default_PC |
Jacket_Default_Mobile |
Jacket_Alt_PC |
Jacket_Alt_Mobile |
| Element 2 | Corresponding jacket slot |
Appearance/JacketAlt Bool |
Same list position and Bool type |
Use materials and shaders supported by each target platform. VRChat's Android guidance notes that avatars do not have access to every shader or avatar component available on PC.
VRChat synchronizes cross-platform custom parameters by their position and type rather than their name. Use the same VRC Expression Parameters asset for both versions even when the animation clips reference different platform materials.
Review Material and Texture Costs
Check these statistics after the material variants are included:
| Statistic | What VRChat measures |
|---|---|
| Material Slots | Slots on Renderer components; each slot corresponds to a submesh and draw call |
| Texture Memory | Estimated memory used by the avatar's textures |
| Mesh Renderers | Skinned and basic renderer component counts |
Swapping the reference in one existing slot keeps the renderer at the same slot count. Adding extra slots to hold variants simultaneously increases the slot count and submesh work instead.
Review the built avatar's texture-memory result rather than judging it by download size. VRChat specifically warns that high-resolution textures can consume far more VRAM than their file size suggests.
Test the Swap
Use a private upload for every supported platform:
| Test | Expected result |
|---|---|
| Avatar loads | Default material appears in the intended slot |
| Toggle turns on | Alternate material appears immediately |
| Toggle turns off | Default material returns immediately |
| Repeat five times | Both transitions remain reversible |
| Inspect other submeshes | Eyes, skin, and unrelated slots do not change |
| Open a mirror | Mirror shows the selected material |
| Ask another user to observe | Remote material agrees when Synced is enabled |
| Switch avatar and return | Saved or Default behavior matches the parameter settings |
| Reset the avatar | Default material returns |
| Test mobile build | Mobile material and corresponding slot work |
| Open Avatar Stats | Material-slot and texture-memory results are acceptable for the build |
Troubleshooting
Help! The menu changes but the material does not.
Compare the Bool name in the menu, Expression Parameters asset, FX Animator parameter, and transitions. Then inspect whether the animation clips contain the intended renderer material binding.
Help! The wrong part of the mesh changes material.
Check the recorded material slot index against the renderer's current Materials list. A clip aimed at Element 1 cannot control a jacket currently assigned to Element 2.
Help! The Animation Clip reports a missing renderer.
The renderer was probably renamed or re-parented after recording. Restore its previous path or record the material reference again from the avatar root.
Help! The material starts in the wrong state.
Align the renderer's prefab material, Expression Parameter Default, FX Bool default, and FX layer default state. Reset the avatar if a Saved value is restoring the alternate state.
Help! The swap works only in one direction.
Add the missing reverse transition. The alternate state must return to the default state when Appearance/JacketAlt becomes false.
Help! The material is pink on mobile.
Inspect the material used by the mobile avatar version and replace it with a shader supported by that target. Confirm both the default and alternate mobile clips reference the mobile materials.
Help! Other users see the default material.
Enable Synced on the Bool and confirm the observer receives a platform version containing the corresponding alternate material clip and renderer slot.
Help! Texture memory increased after adding variants.
Inspect the textures referenced by both material variants and the built avatar's texture-memory total. Reduce unnecessary texture resolution or reuse suitable maps where the appearances allow it.
Official References
- Expressions Menu and Controls
- Playable Layers
- Avatar Performance Ranks
- Avatar Optimization Tips
- Per-Platform Avatar Overrides
- Unity Materials
Continue with Avatar Materials
- Create a Material Swap Radial Menu
- Animate an Avatar Hue Shift
- Create an RGB Radial Slider
- Create a VRChat Avatar Object Toggle
- Save VRChat Avatar Toggle States
- Avatar Optimization Checklist
Topics: material swaps, renderer slots, FX Animator, avatar customization