跳转至

title: Expression Menu 配置 description: V3版 — VRChat 菜单系统配置,参数示例对齐 taozhuang created: 2026-05-09 updated: 2026-05-27 type: reference tags: [vrchat, avatar, expression-menu, parameters, vrcsdk, v3, taozhuang]


Expression Menu 配置

[!NOTE] 本文档为 V3 版本,菜单示例中的服装参数已更新为 taozhuang(Int, 0-3)。 V3 服装切换使用 Button 控件直接赋值 taozhuang 值,而非 Toggle。

核心组件

1. VRCExpressionsMenu

路径:在 Project 中创建的 ScriptableObject

位置:通常在 Assets/.../EXMenu/

例子: - Assets/Cazalis/Animation/EXMenu/Cazalis_Menu.asset

2. VRCExpressionParameters

路径Assets/.../EXMenu/Cazalis_Parameter.asset

用途:定义所有 VRC 参数(Bool/Int/Float)

3. VRCAvatarDescriptor

属性: - expressionsMenu — 关联的菜单资产 - expressionParameters — 关联的参数资产 - customExpressions — 是否启用自定义表达式

控制类型 (ControlType)

类型 说明 对应参数
101 Button 按钮,按下触发一次 Int/Float
102 Toggle 开关,true/false 切换 Bool
103 SubMenu 子菜单,进入二级菜单 无参数
201 TwoAxisPuppet 二轴控制器 Float x2
202 FourAxisPuppet 四轴控制器 Float x4
203 RadialPuppet 径向控制器 Float x1

菜单结构设计

| 202 | FourAxisPuppet | 四轴控制器 | Float x4 | | 203 | RadialPuppet | 径向控制器 | Float x1 |

菜单结构设计### V3 目标菜单

根菜单 (Cazalis_Menu)
├── 蝴蝶结 (Toggle) → Butterfly_ON
├── 服装 (SubMenu)
│   ├── 原皮 (Button) → taozhuang = 0
│   ├── 露肩短裙 (Button) → taozhuang = 1
│   ├── 休闲服 (Button) → taozhuang = 2
│   ├── 开衫毛衣 (Button) → taozhuang = 3
│   └── Blanchir (Button) → taozhuang = 5
├── 发型 (SubMenu)
│   ├── 短发 (Toggle) → Hair = 0
│   └── 长发 (Toggle) → Hair = 1
└── 缩放 (SubMenu)
    ├── 胸部大小 (Radial) → Breasts_Size
    └── 腿粗细 (Radial) → Futomomo_Size

[!NOTE] V3 服装切换使用 Button 控件(类型 101),而非 Toggle,直接赋值 taozhuang 参数(Int 0-5,其中4对应娃花)。 如需内衣穿透等 Bool 开关,仍使用 Toggle 控件。

添加菜单项(C# 代码)

添加服装 Button(V3 taozhuang)

using VRC.SDK3.Avatars.ScriptableObjects;

VRCExpressionsMenu menu = AssetDatabase.LoadAssetAtPath<VRCExpressionsMenu>(
    "Assets/Cazalis/Animation/EXMenu/Cazalis_Menu.asset"
);

VRCExpressionsMenu.Control button = new VRCExpressionsMenu.Control();
button.name = "露肩短裙";
button.type = (VRCExpressionsMenu.Control.ControlType)101; // Button

button.parameter = new VRCExpressionsMenu.Control.Parameter();
button.parameter.name = "taozhuang";

List<VRCExpressionsMenu.Control> controls = menu.controls.ToList();
controls.Add(button);
menu.controls = controls.ToArray();

EditorUtility.SetDirty(menu);
AssetDatabase.SaveAssets();
; menu.controls = controls.ToArray();

EditorUtility.SetDirty(menu); AssetDatabase.SaveAssets(); ```### 添加 Bool Toggle

using VRC.SDK3.Avatars.ScriptableObjects;

VRCExpressionsMenu.Control toggle = new VRCExpressionsMenu.Control();
toggle.name = "内衣";
toggle.type = (VRCExpressionsMenu.Control.ControlType)102; // Toggle

toggle.parameter = new VRCExpressionsMenu.Control.Parameter();
toggle.parameter.name = "Bra"; // 对应 Animator Bool 参数

List<VRCExpressionsMenu.Control> controls = menu.controls.ToList();
controls.Add(toggle);
menu.controls = controls.ToArray();

EditorUtility.SetDirty(menu);
AssetDatabase.SaveAssets();

参数配置

VRCExpressionParameters

VRCExpressionParameters parameters = AssetDatabase.LoadAssetAtPath<VRCExpressionParameters>(
    "Assets/Cazalis/Animation/EXMenu/Cazalis_Parameter.asset"
);

// V3 taozhuang 参数定义
VRCExpressionParameters.Parameter taozhuangParam = new VRCExpressionParameters.Parameter
{
    name = "taozhuang",
    valueType = VRCExpressionParameters.ValueType.Int,
    defaultValue = 0f,
    saved = true,
    networkSynced = true
};

// 例如在参数数组中添加
parameters.parameters[0] = taozhuangParam;

EditorUtility.SetDirty(parameters);
AssetDatabase.SaveAssets();

参数属性

属性 说明
name 参数名(与 Animator 参数对应)
valueType Bool / Int / Float
defaultValue 默认值
saved 是否保存到服务器
networkSynced 是否网络同步

Float | | defaultValue | 默认值 | | saved | 是否保存到服务器 | | networkSynced | 是否网络同步 |

VRCExpressionsMenu subMenu = new VRCExpressionsMenu();

// V3 服装子菜单
subMenu.controls = new VRCExpressionsMenu.Control[]
{
    new VRCExpressionsMenu.Control {
        name = "原皮",
        type = (VRCExpressionsMenu.Control.ControlType)101, // Button
        parameter = new VRCExpressionsMenu.Control.Parameter { name = "taozhuang" },
        value = 0f
    },
    new VRCExpressionsMenu.Control {
        name = "露肩短裙",
        type = (VRCExpressionsMenu.Control.ControlType)101, // Button
        parameter = new VRCExpressionsMenu.Control.Parameter { name = "taozhuang" },
        value = 1f
    },
    new VRCExpressionsMenu.Control {
        name = "休闲服",
        type = (VRCExpressionsMenu.Control.ControlType)101, // Button
        parameter = new VRCExpressionsMenu.Control.Parameter { name = "taozhuang" },
        value = 2f
    },
    new VRCExpressionsMenu.Control {
        name = "开衫毛衣",
        type = (VRCExpressionsMenu.Control.ControlType)101, // Button
        parameter = new VRCExpressionsMenu.Control.Parameter { name = "taozhuang" },
        value = 3f
    },
    new VRCExpressionsMenu.Control {
        name = "Blanchir",
        type = (VRCExpressionsMenu.Control.ControlType)101, // Button
        parameter = new VRCExpressionsMenu.Control.Parameter { name = "taozhuang" },
        value = 5f
    }
};

AssetDatabase.CreateAsset(subMenu, "Assets/MySubMenu.asset");

已知问题

 value = 5f
}

};

AssetDatabase.CreateAsset(subMenu, "Assets/MySubMenu.asset");

## 已知问题### 参数引用未设置

添加 Toggle 控制项后,`parameter` 属性可能为 null:

```csharp
// 错误:parameter 未设置
control.parameter = null; // ❌

// 正确:引用正确的参数对象
VRCExpressionParameters.Parameter targetParam = Array.Find(parameters.parameters, 
    p => p.name == "Bra");
control.parameter = targetParam; // ✅

命名大小写

Animator 参数名区分大小写: - BrabraBRA

绑定到 Avatar

在 VRCAvatarDescriptor 中

VRCAvatarDescriptor descriptor = avatar.GetComponent<VRCAvatarDescriptor>();

// 启用自定义表达式
descriptor.customExpressions = true;

// 关联菜单
descriptor.expressionsMenu = menuAsset;

// 关联参数
descriptor.expressionParameters = parametersAsset;

相关资源