跳转至

title: Cazalis 溶解换衣系统实战记录(V3) description: 2026-05-27 V3版 — Cazalis zigai 5套衣服溶解换衣系统(含Blanchir),基于 Cazalis_FX_Modified_V3.controller created: 2026-05-10 updated: 2026-05-28 type: case-study tags: [vrchat, cazalis, dissolve, liltoon, animator, v3]


Cazalis 溶解换衣系统实战记录(V3)

[!NOTE] 本文档为 V3 版本(基于 Cazalis_FX_Modified_V3.controller),对应审计报告 dissolve-transition-system-cazalis.md 的修正版。 如需查看 V3 之前版本(已废弃),请参考 dissolve-transition-system-cazalis-legacy.md

V3 核心变更:参数 Wardrobe_Int1taozhuang,Layer 索引 21-24 → 18-21,Clip 路径更新为 yuanpi/mox/xiuxian/ksmy

架构概览

  • Controller: Assets/Cazalis/Animation/Animator/Cazalis_FX_Modified_V3.controller(27层,索引 0-26)
  • Dissolve Clips: Assets/Cazalis/Animation/FX/yuanpi/mox/xiuxian/ksmy/Blanchir/
  • 控制参数: taozhuang(Int, saved=true, default=0)
  • 5个溶解 Layer,index 18-22 + 25,Override 模式
  • 1个内衣控制 Layer,index 26,Override 模式,weight=1.0

Layer 对应关系

|| Layer | 名称 | Int值 | 衣服 | |-------|------|-------|------| | 18 | 4S_Origin | 0 | 原皮(yuanpi) | | 19 | 4S_Lujian | 1 | 露肩短裙(mox) | | 20 | 4S_Casual | 2 | 休闲服(xiuxian) | | 21 | 4S_Cardigan | 3 | 开衫毛衣(ksmy) | | 22 | 4S_Wahua | 4 | 娃花 | | 25 | 4S_Blanchir | 5 | 绑带上衣(Blanchir) | | 26 | 4S_Underwear | - | 内衣统一控制层 |

注:taozhuang=4 对应娃花(现有换装菜单第5项),不在4S溶解层中。 5 | 绑带上衣(Blanchir) | | 26 | 4S_Underwear | - | 内衣统一控制层 |

注:taozhuang=4 对应娃花(现有换装菜单第5项),不在4S溶解层中。### 4 状态循环(V3 标准命名)

两条独立的判断路径:

穿上线: A_Closed → (taozhuang == val) → B_Appearing → (ON clip 播完) → C_Opened 脱下线: C_Opened → (taozhuang != val) → D_Disappearing → (OFF clip 播完) → A_Closed

⚠️ 旧版命名(已废弃):Hide/Appear/Show/Disappear → 请统一使用 V3 标准:A_Closed / B_Appearing / C_Opened / D_Disappearing

各状态含义: - A_Closed:默认状态,保持溶解隐藏(_DissolveParams.z = 1.7, m_IsActive = 0) - B_Appearing:条件满足时进入,播放 ON clip(_DissolveParams.z 1.7 → -0.5) - C_Opened:ON clip 播完后进入,保持可见(_DissolveParams.z = -0.5, m_IsActive = 1) - D_Disappearing:条件不满足时进入,播放 OFF clip(_DissolveParams.z -0.5 → 1.7) - OFF clip 播完后 必须有 Transition 跳回 A_Closed,否则状态机卡住

stateDiagram-v2
    A_Closed --> B_Appearing : taozhuang == val
    B_Appearing --> C_Opened : ON clip 播放完毕 (1秒)
    C_Opened --> D_Disappearing : taozhuang != val
    D_Disappearing --> A_Closed : OFF clip 播放完毕 (1秒)
pened --> D_Disappearing : taozhuang != val D_Disappearing --> A_Closed : OFF clip 播放完毕 (1秒) ```### 状态机 vs 动画的区别

层面 负责什么 例子
Animator 状态机 什么时候播什么动画 A_Closed → B_Appearing 的 Transition 条件 taozhuang == val
动画层 状态里持有的 AnimationClip B_Appearing 状态持 ON clip,C_Opened 状态持 Show clip 等
AnimationClip 进入状态后具体怎么动 _DissolveParams.z 从 1.7 走到 -0.5

对应关系:

状态机层:  A_Closed  →  B_Appearing  →  C_Opened  →  D_Disappearing  →  A_Closed
                     ↓                 ↓              ↓
动画层:     OFF值      ON clip        Show clip      OFF clip

每个状态需要配置: - 自己持有的 clip(进入后播放的内容) - 到下一个状态的 Transition(播完后怎么跳)

Transition 条件说明:

路径 条件 类型
A_Closed → B_Appearing taozhuang == val 穿上线:参数匹配时显现
B_Appearing → C_Opened ON clip 播放完毕 播完自动跳
C_Opened → D_Disappearing taozhuang != val 脱下线:参数不匹配时溶解
D_Disappearing → A_Closed OFF clip 播放完毕 播完自动跳回隐藏

⚠️ 遗漏 D_Disappearing → A_Closed 的 Transition 是常见错误:OFF clip 播完后状态机卡在 D_Disappearing 结束位置,再次触发切换时条件冲突导致卡顿。

材质配置标准(lilToon 溶解效果)

一、渲染模式

  • 镂空(Cutout) ✅ — 使用 Hidden/lilToonCutout
  • 透明(Transparent) — 透明必须使用 Two Pass,对应 Hidden/lilToonTwoPassTransparent den/lilToonCutout`
  • 透明(Transparent) — 透明必须使用 Two Pass,对应 Hidden/lilToonTwoPassTransparent### 二、溶解设置
项目 说明
溶解方式 UV 不是世界坐标
形状 点(Point) _DissolveParams.x = 2
坐标 X 0 _DissolvePos.x = 0
坐标 Y 1 _DissolvePos.y = 1
噪点图 Cazalis_Reflection_Noise Assets/Cazalis/Cazalis_Reflection_Noise.png
噪点强度 0.3 _DissolveNoiseStrength = 0.3
纹理颜色 #387AE9 RGB: (56, 122, 233)
边界(完全显现) -0.5 _DissolveParams.z = -0.5
边界(完全溶解) 1.7 _DissolveParams.z = 1.7
边界默认值 -0.5 默认可见,不溶解
Shader Keyword GEOM_TYPE_BRANCH_DETAIL 必须启用
动画过渡时间 1.1 秒 2026-05-28 从1.2s改为1.1s

三、Clip 中溶解参数动画

Clip 作用 _DissolveParams.z 变化 m_IsActive
A_Closed(OFF 值) 保持隐藏 1.7 保持不变 自己的 SMR = 0
ON(显现) 衣服出现 1.7 → -0.5 结束时 m_IsActive = 1
OFF(溶解) 衣服消失 -0.5 → 1.7 结束时 m_IsActive = 0
C_Opened(Show 值) 保持显示 -0.5 保持不变 自己的 SMR = 1
-0.5 → 1.7 结束时 m_IsActive = 0
C_Opened(Show 值) 保持显示 -0.5 保持不变 自己的 SMR = 1

原皮 (8 SMR): - Cazalis_Cloth.mat — Cutout - Cazalis_Cloth_Alpha.mat — TwoPassTransparent - Cazalis_Pumps.mat — Cutout - Cazalis_Hair.mat — Cutout - Cazalis_Underwear_Bra.mat — Cutout - Cazalis_Underwear_Shorts.mat — Cutout

露肩短裙 (12 SMR)Assets/choco/Seraphic Bloom Dress/Material/: - Tex1_2_1.mat — TwoPassTransparent - Tex2_2.mat — Cutout - Tex3_2.mat — Cutout - Tex4_2_1.mat — Cutout - M.mat — Cutout - C.mat — Gem (skip)

休闲服 (5 SMR)Assets/AyuElla/SilentSkinPeek/Material/: - Stripe_White.mat — TwoPassTransparent - accessory.mat — TwoPassTransparent

开衫毛衣 (8 SMR)Assets/Rest/Awakoi_Code/Mat/: - Cloud.mat (UV2/Outer) — Cutout - Cloud.mat (UV1/Tops) — Cutout - Cloud.mat (UV1/Pants) — Cutout - Cloud.mat (UV1/Tops_Ribbon) — Cutout - Mono.mat (UV1/Leg_Ribbon) — Cutout - Brown.mat (UV2/Boots) — Cutout - Brown.mat (UV2/Frill) — TwoPassTransparent

Blanchir (3 SMR)Assets/Cazalis/Qukumu/Blanchir/Cazalis/Data/: - blanchir Cazalis.mat — Cutout/Transparent(单一材质覆盖3个SMR) - 材质溶解参数: DP=(2,0,1.7,0), DissolvePos=(0,1,0,0), NoiseMask=Cazalis_Reflection_Noise, NoiseStrength=0.3, DissolveColor=(0.22,0.48,0.91,1) s=(0,1,0,0), NoiseMask=Cazalis_Reflection_Noise, NoiseStrength=0.3, DissolveColor=(0.22,0.48,0.91,1)## V3 Clip 路径

衣服 taozhuang 值 ON Clip OFF Clip
原皮 0 yuanpi_ON.anim yuanpi_OFF.anim
露肩短裙 1 mox_ON.anim mox_OFF.anim
休闲服 2 xiuxian_ON.anim xiuxian_OFF.anim
开衫毛衣 3 ksmy_ON.anim ksmy_OFF.anim
Blanchir 5 blanchir_ON.anim blanchir_OFF.anim

Clip 存放路径:Assets/Cazalis/Animation/FX/yuanpi/ / mox/ / xiuxian/ / ksmy/ / Blanchir/(Blanchir大写B开头)

[!WARNING] V3 之前(旧版 Wardrobe_Int1 方案)使用 Origin_Dissolve_*.anim,各套装共用同一套 clip,导致切换时显示错乱。V3 必须每套衣服独立 ON/OFF clip,且 clip 内只控制自己那套的 SMR。

Blanchir 第5套换装(2026-05-27 新增)

概要

Blanchir 是 Cazalis zigai02 的第5套换装,3个 SMR(内衬/裙子/上衣),共用单一材质 blanchir Cazalis.mat

动画层配置

  • Layer 名称: 4S_Blanchir
  • Layer 索引: 25
  • 参数: taozhuang = 5(Int, saved=true, default=0)
  • Override 模式
  • 状态/过渡/条件: 与现有 4 套(Origin/Lujian/Casual/Cardigan)完全一致

动画 Clip

Clip 路径 作用
Blanchir_ON.anim Assets/Cazalis/Animation/FX/ 溶解显现,_DissolveParams.z 1.7 → -0.5
Blanchir_OFF.anim Assets/Cazalis/Animation/FX/ 溶解消失,_DissolveParams.z -0.5 → 1.7
Blanchir_Hide.anim Assets/Cazalis/Animation/FX/ A_Closed 状态隐藏,维持 _DissolveParams.z = 1.7

注:Clip 仅包含材质溶解参数和 m_IsActive 曲线,无骨骼位置/旋转曲线。

菜单配置

  • 菜单名: 绑带上衣(原英文名 Blanchir 已改名)
  • 图标: Assets/Auto_Iron/blanchir.png(GUID=5db9f00dca0ac3240bf9abf2ffac4837, 512×512)
  • taozhuang 值: 5 Assets/Auto_Iron/blanchir.png(GUID=5db9f00dca0ac3240bf9abf2ffac4837, 512×512)
  • taozhuang 值: 5### Boots ShapeChanger

Blanchir_Cazalis/Boots 已补全 ModularAvatarShapeChanger 组件: - 3个 blendshape:Shrink_Toe=100, Shrink_Foot=100, Shrink_Ankle=100 - referencePath="Body_Base",ChangeType=Set - 配置与 Cloud/Boots 完全一致

材质溶解参数

属性 说明
_DissolveParams (2, 0, 1.7, 0) x=2=Point模式, z=1.7=完全溶解
_DissolvePos (0, 1, 0, 0) 从头顶溶解
_DissolveNoiseMask Cazalis_Reflection_Noise 项目统一噪点图
_DissolveNoiseStrength 0.3 噪点强度
_DissolveColor (0.22, 0.48, 0.91, 1) 溶解边缘蓝色光晕 (#387AE9)

Blanchir Prefab 配置

  • Prefab: Blanchir_Cazalis.prefab(MA 预配置版)
  • 根缩放: 建议 1.04(匹配 zigai 体型)
  • 骨骼合并: Armature.1 带有 ModularAvatarMergeArmature 组件,MA 构建时自动合并
  • 无鞋子部件: Foot_Heel = 0,符合规则

A_Closed 配置说明

⚠️ 文档勘误:原文档错误标注 A_Closed 状态不能设 writeDefaultValues=true。正确做法有两种:

  1. 理论推荐: writeDefaultValues=true + 搭配 Hide clip(Hide clip 的 w 值建议 0.1,w=0 会导致溶解边缘锯齿)
  2. Cazalis 实际做法: 所有 5 套 4S 层的 A_Closed 都用 OFF clip + writeDefaultValues=false,在 VRChat 中验证正常工作

Blanchir 新层按现有 4 套做法配置以保持一致。

内衣统一控制层 — Layer 26 (4S_Underwear)(2026-05-28 新增)

问题背景

原皮和抹胸切换时 Shorts(内裤)不显示。根因:多层 Override 冲突 — 5个衣服层都是 Override 模式,每个层的 OFF clip 都写了 Shorts/Bra 的隐藏值。当原皮/抹胸层用 ON clip 显示 Shorts 时,其他未激活层的 OFF clip 在后面覆盖了 ON clip 的值。

修复方案

  1. 从所有10个 ON/OFF clip 移除 Shorts/Bra 曲线(40条),消除多层覆盖冲突
  2. 新建 Layer 26 4S_Underwear 专用层统一管理内衣显隐
  3. 修复 Layer 26 的 defaultWeight=0→1.0(新建层默认 weight=0 不生效) 突
  4. 新建 Layer 26 4S_Underwear 专用层统一管理内衣显隐
  5. 修复 Layer 26 的 defaultWeight=0→1.0(新建层默认 weight=0 不生效)### Layer 26 架构
Hide (default) ←→ ShowShorts

2状态: - Hide:Shorts m_IsActive=0 + _DissolveParams.z=1.7,Bra m_IsActive=0 + z=1.7 - ShowShorts:Shorts m_IsActive=1 + z=-0.5,Bra m_IsActive=0 + z=1.7

6个过渡条件: - Hide → ShowShorts:taozhuang == 0(原皮)/ taozhuang == 1(抹胸)/ taozhuang == 5(绑带上衣) - ShowShorts → Hide:taozhuang == 2(休闲)/ taozhuang == 3(开衫)/ taozhuang == 4(全脱)

配置: - blendingMode = Override - defaultWeight = 1.0(⚠️ 必须手动设,新建层默认为0) - 过渡时间 = 1.1s(与衣服溶解同步)

显隐对照表

taozhuang 衣服 Shorts Bra Layer 26 状态
0 原皮 ShowShorts
1 露肩短裙 ShowShorts
2 休闲服 Hide
3 开衫毛衣 Hide
4 全脱 Hide
5 绑带上衣 ShowShorts

动画文件

Clip 路径 内容
Underwear_Hide.anim Assets/Cazalis/Animation/FX/ Shorts a=0 z=1.7, Bra a=0 z=1.7
Underwear_ShowShorts.anim Assets/Cazalis/Animation/FX/ Shorts a=1 z=-0.5, Bra a=0 z=1.7

| Underwear_ShowShorts.anim | Assets/Cazalis/Animation/FX/ | Shorts a=1 z=-0.5, Bra a=0 z=1.7 |### ⚠️ Layer defaultWeight 陷阱

通过 C# API 创建 AnimatorControllerLayer 时,defaultWeight 默认为 0,层不会生效。必须手动设为 1.0。

修复方法:

var newLayer = new AnimatorControllerLayer();
newLayer.name = l26.name;
newLayer.stateMachine = l26.stateMachine;
newLayer.defaultWeight = 1f;
newLayer.blendingMode = AnimatorLayerBlendingMode.Override;
var layers = fx.layers;
layers[26] = newLayer;
fx.layers = layers;
EditorUtility.SetDirty(fx);
AssetDatabase.SaveAssetIfDirty(fx);

过渡时间调整(2026-05-27)

5 个 4S 换装层共 10 条溶解过渡(每层出现 + 消失各 1 条)时长统一调整为 1.1 秒,其余非溶解过渡保持 0 秒不变。Layer 26 (4S_Underwear) 的过渡也使用 1.1 秒。

调整历程:1s → 1.5s → 1.2s → 最终 1.1s。 1.1 秒,其余非溶解过渡保持 0 秒*不变。Layer 26 (4S_Underwear) 的过渡也使用 1.1 秒。

调整历程:1s → 1.5s → 1.2s → 最终 1.1s。## 失败教训

  1. 材质写不入问题: 对 choco/AyuElla/Rest/ 目录下的材质调用 mat.SetFloat("_DissolveParams.z", 1.7f) 无效(缓存问题)。必须直接编辑 .mat 文件内容然后 AssetDatabase.Refresh()

  2. 不能共用 dissolve clip: 一开始所有衣服用了同一个 Origin_Dissolve_ON.anim,但该 clip 内写死了原皮的 m_IsActive 状态,导致切到其他衣服时显示错乱。每套衣服必须有自己的 ON/OFF/Show clip,只控制自己那套的 SMR

  3. lilToon 渲染模式: 普通 lilToon shader 是不透明的,必须换到 Hidden/lilToonCutoutHidden/lilToonTwoPassTransparent 变体。不能只靠 _TransparentMode 参数。

  4. 切换卡顿(未解决): 快速切换衣服时有时会卡住。怀疑多个 dissolve layer 同时播放导致状态机冲突。可能的解决方向:减少同时激活的 dissolve layer,或加保护逻辑。

  5. Hide clip w 值: Hide clip 的 w 值(_DissolveParams 的 a 分量)不应设为 0,最佳实践为 0.1。w=0 会导致溶解边缘出现锯齿。

  6. 多层 Override 冲突(2026-05-28 已解决): 多个 Override 层同时写同一属性时,后面的层会覆盖前面的值。原本5个衣服层的 OFF clip 都写了 Shorts/Bra 的隐藏值,导致原皮/抹胸层的 ON clip 显示 Shorts 时被其他层覆盖。解决方案:将冲突属性(Shorts/Bra)提取到专用 Layer 26 (4S_Underwear) 统一管理,不在多个层中重复写入同一属性。

  7. 新建 Layer 的 defaultWeight=0 陷阱(2026-05-28 发现): 通过 C# API 创建 AnimatorControllerLayer 时 defaultWeight 默认为 0,层不会生效。必须手动创建副本设 defaultWeight=1.0 再替换回 layers 数组。直接修改 layers[idx].defaultWeight 不生效,因为 layers[idx] 返回的是副本。 创建副本设 defaultWeight=1.0 再替换回 layers 数组。直接修改 layers[idx].defaultWeight 不生效,因为 layers[idx] 返回的是副本。8. Skill 模板 bug(已修复): 共修复 14 个 VRChat 溶解相关 skill 的 bug,严重问题包括:

  8. cazalis-dissolve-system-v3: 错误标注 A_Closed 不能设 writeDefaultValues=true,正确应为 wd=true + Hide clip
  9. liltoon-dissolve-material-batch: YAML 中 _DissolveParams 的 a 值误设为 0,应改为 0.1
  10. vrchat-4state-toggle-dissolve-system: hideClip 未定义 bug,导致编译失败
  11. vrchat-dissolve-transition-system: AnimatorConditionMode 补全等修复 em:hideClip` 未定义 bug,导致编译失败
  12. vrchat-dissolve-transition-system: AnimatorConditionMode 补全等修复## 项目路径

  13. 项目根: E:/ALCOM/project/Cazalis

  14. V3 Controller: Assets/Cazalis/Animation/Animator/Cazalis_FX_Modified_V3.controller
  15. Dissolve Clips: Assets/Cazalis/Animation/FX/yuanpi/mox/xiuxian/ksmy/
  16. 材质分散在 4 个目录:
  17. Assets/Cazalis/Material/ — 原皮
  18. Assets/choco/Seraphic Bloom Dress/Material/ — 露肩短裙
  19. Assets/AyuElla/SilentSkinPeek/Material/ — 休闲服
  20. Assets/Rest/Awakoi_Code/Mat/ — 开衫毛衣
  21. Assets/Cazalis/Qukumu/Blanchir/Cazalis/Data/ — Blanchir