Skip to content

换装管线闭环设计 ​

虚拟形象换装不是「预设套装切换」,而是任意部件的独立建模、独立加载、运行时拼接——这条管线要从美术制作规范一路闭环到运行时的骨骼合并,任何一环松掉,用户看到的就是穿模或者换装卡死。

首次换装≈1–2s
缓存命中<100ms
蒙皮限制4 骨骼/顶点

背景 ​

B 站虚拟形象允许用户自由搭配衣服、裙子、翅膀、头发等部件。和传统游戏的预设套装不同,这里是任意组合:每个部件独立建模、独立压缩、独立下载,运行时拼到同一个角色身上。这意味着管线必须同时回答三个问题:美术按什么规范做,资源按什么格式发,运行时怎么把不同部件的骨骼拼成一套。

换装管线闭环设计

问题 ​

问题表现根因方向
部件各自带骨骼裙子、翅膀自带的骨骼和身体骨架对不上缺少统一骨架规范
组合冲突裙子和裤子同时穿必穿模缺少槽位与互斥规则
移动端蒙皮超限低端机 GPU 蒙皮寄存器有限每顶点骨骼影响数无约束
换装卡顿下载、解压、合并全在主链路无缓存与异步化
连续换装泄漏换十几次后内存持续上涨旧 Mesh/纹理未释放

方案 ​

mermaid
flowchart LR
  A["美术制作<br>统一骨架/蒙皮规范"] --> B["资源打包<br>glb + ktx2 + 部件配置"]
  B --> C["配置系统<br>槽位/互斥/依赖"]
  C --> D["运行时加载<br>Draco 解压/KTX2 上传"]
  D --> E["换装引擎<br>骨骼合并 + 重绑定"]
  E --> F["SkinnedMesh 更新"]

1. 资源制作规范(美术侧闭环) ​

  • 所有部件使用同一套骨架,统一命名、统一层级,禁止部件模型里加独立骨骼;
  • 蒙皮约束:每根骨骼最多影响 4 个顶点(移动端限制),蒙皮权重总和 = 1.0。

规范的意义是把运行时合并的成本前置到制作期消化——部件不夹带私货骨骼,合并时只需要做引用对齐,不需要做拓扑缝合。

2. 打包配置(工程化侧闭环) ​

每个部件一份 JSON 配置:

json
{
  "id": "w_skirt_001",
  "type": "skirt",
  "slot": "bottom",
  "model": "w_skirt_001.glb",
  "textures": ["tex_default.ktx2"],
  "bones": ["Hips", "Spine"],
  "collision": "none"
}

配置系统负责三件事:槽位(body / top / bottom / hair / wing),互斥(skirt 和 pants 同属 bottom 槽位,互斥),依赖检查(翅膀依赖身体模型的背骨节点,身体没加载完翅膀排队)。

换装资源管线操作说明

3. 运行时换装管线 ​

用户选择部件 → 检查槽位互斥 → 请求下载模型 → Draco 解压 → KTX2 上传 GPU
  → 合并骨骼 → 更新 SkinnedMesh → 换装完成

关键实现:骨骼合并 ​

整条管线最难的一环:不同部件的骨骼是独立的,必须合并到同一个 Skeleton 才能共用一套动画。

身体骨骼 (60 bones) + 裙子骨骼 (5 bones,引用身体的 Hips, Spine)
  → 合并为 65 bones 的统一 Skeleton
  → 裙子 Mesh 重新绑定到合并后的 Skeleton

合并骨骼

蒙皮与骨骼

合并后部件 Mesh 的蒙皮索引要重映射到新 Skeleton 的骨骼下标,这一步做错了模型会「炸」成放射状碎片——调试期最常见的画面。配合制作期「禁止独立骨骼」的规范,合并实际退化成「查找引用骨骼在新 Skeleton 中的下标并替换」,稳定且快速。

指标 ​

场景耗时/表现
首次换装下载 + 解压 + 骨骼合并 ≈ 1–2s
再次换同一部件缓存命中,< 100ms
连续换装无内存泄漏(修复旧 Mesh/纹理释放后)
蒙皮规格每顶点 ≤ 4 骨骼影响,权重和 = 1.0

复盘 ​

  1. 换装系统的稳定性七分靠制作规范,三分靠运行时代码——运行时能做的兜底很有限,规范必须在美术侧就卡住。
  2. 槽位 + 互斥 + 依赖检查要放在配置层表达,不要散在换装代码的 if 里,否则新增部件类型时必漏。
  3. 骨骼合并尽量让它「退化成下标重映射」;如果需要真的缝骨骼树,说明上游规范已经破了。
  4. 缓存和释放要成对设计:缓存让二次换装进 100ms,释放漏了连续换装就变成内存事故。

罗子初 · AI 座舱专家 · 8年端侧研发

Lv.1