Appearance
虚拟形象 Unity → Three.js 迁移
主导 B 站虚拟形象从 Unity WebGL 到 Three.js 的技术选型与迁移,解决 WebGL 在移动端的性能天花板。
背景
B 站用户虚拟形象 1.0 使用 Unity WebGL 方案。但 Unity WebGL 在移动端的性能表现有天花板——编译体积大、启动慢、内存占用高。
2.0 版本需要覆盖更多低端机型,Unity WebGL 无法满足。
技术选型:为什么选 Three.js
| 维度 | Unity WebGL | Three.js |
|---|---|---|
| 渲染效果 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐(可塑性高) |
| 机型覆盖率 | 30% | 目标 90%+ |
| 启动速度 | 慢(10s+) | 快(< 3s) |
| 包体积 | 大(10-20MB+) | 小(< 2MB JS) |
| 开发效率 | 中(导出调试慢) | 高(HMR) |
| 生态 | 3D 游戏 | Web 原生 |
最终选择:Three.js,因其渲染效果可塑性高且Web 原生。
迁移过程
1. 模型转换
Unity 模型 → GLB/GLTF 导出 → Three.js GLTFLoader 加载- Unity 的 Animator → Three.js AnimationMixer
- Unity 的 BlendShape → Three.js MorphTarget
- 骨骼动画映射验证:抽检 20 个动画确保无变形
2. 渲染效果对齐
Unity Standard Shader → Three.js MeshStandardMaterial
Unity Toon Shader → 手写 Three.js Shader(基于卡通渲染算法)- 贴图格式:PNG → KTX2(GPU 原生压缩)
- 光照模型:PBR 参数调优,与 Unity 效果对齐
3. 面捕接入
Mediapipe Web SDK → CompatibleFaceData 协议 → Three.js MorphTarget 驱动面捕解算器从 C# 移植到 JavaScript(核心算法一致)。
4. Three.js 底层修改
WebGLMotionVector 类源码修改:
- 根因:换装部件切换时,旧 Mesh 的 WebGL 资源(纹理、Buffer)未正确释放
- 修复:在
dispose()方法中增加gl.deleteTexture()和gl.deleteBuffer()的级联调用 - 验证:连续换装 100 次,内存稳定无泄漏
5. 性能优化(详见 Web 端 11→30 FPS + WebGL 30%→93% 文章)
结果
| 指标 | Unity WebGL | Three.js |
|---|---|---|
| 覆盖率 | 30% | 93% |
| 低端机帧率 | — | 30fps |
| 启动速度 | 10s+ | < 3s |
| 内存 | 高 | 可控 |
教训
- 技术选型不是"哪个技术更好",是"哪个技术更适合当前的用户设备分布"
- 不要害怕改底层源码——Three.js 的 WebGLMotionVector 被改了才根治内存泄漏
- 迁移不是重写:面捕核心算法直接平移,资产转换工具自动化
公开版深化
案例定位
虚拟形象 Unity → Three.js 迁移不是孤立笔记,而是虚拟人技术能力下的一个可复用案例。它服务于“性能治理与稳定性优化”这条主线,公开版重点保留问题抽象、工程取舍和可复用方法,不暴露内部系统细节。
关键问题
主导 B 站虚拟形象从 Unity WebGL 到 Three.js 的技术选型与迁移,解决 WebGL 在移动端的性能天花板。
这篇文章已经覆盖 背景、技术选型:为什么选 Three.js、迁移过程、结果、教训。后续阅读时应重点看三件事:问题如何被定义,方案如何在约束下落地,以及哪些经验可以迁移到下一次类似项目。
企业级产出
| 产出 | 公开表达 |
|---|---|
| 问题定义 | 用用户体验、性能、稳定性或交付效率描述影响 |
| 技术方案 | 保留架构、流程、算法和工具链层面的抽象 |
| 指标证据 | 只使用页面已有数字或经过脱敏审查的量级 |
| 复用方法 | 沉淀为 SOP、检查清单、图谱关系或后续案例链接 |
指标与证据
- 机型覆盖率 30% 目标 90%+
- 启动速度 慢(10s+) 快(< 3s)
- 包体积 大(10-20MB+) 小(< 2MB JS)
- 骨骼动画映射验证:抽检 20 个动画确保无变形
复盘结论
这个案例的核心价值,是把一次具体工程处理沉淀成可检索、可复盘、可继续扩展的技术资产。没有公开证据支撑的细节继续留在私有材料池,不进入线上页面。
公开版深化
案例定位
虚拟形象 Unity → Three.js 迁移不是孤立笔记,而是虚拟人技术能力下的一个可复用案例。它服务于“性能治理与稳定性优化”这条主线,公开版重点保留问题抽象、工程取舍和可复用方法,不暴露内部系统细节。
关键问题
主导 B 站虚拟形象从 Unity WebGL 到 Three.js 的技术选型与迁移,解决 WebGL 在移动端的性能天花板。
这篇文章已经覆盖 背景、技术选型:为什么选 Three.js、迁移过程、结果、教训。后续阅读时应重点看三件事:问题如何被定义,方案如何在约束下落地,以及哪些经验可以迁移到下一次类似项目。
企业级产出
| 产出 | 公开表达 |
|---|---|
| 问题定义 | 用用户体验、性能、稳定性或交付效率描述影响 |
| 技术方案 | 保留架构、流程、算法和工具链层面的抽象 |
| 指标证据 | 只使用页面已有数字或经过脱敏审查的量级 |
| 复用方法 | 沉淀为 SOP、检查清单、图谱关系或后续案例链接 |
指标与证据
- 机型覆盖率 30% 目标 90%+
- 启动速度 慢(10s+) 快(< 3s)
- 包体积 大(10-20MB+) 小(< 2MB JS)
- 骨骼动画映射验证:抽检 20 个动画确保无变形
复盘结论
这个案例的核心价值,是把一次具体工程处理沉淀成可检索、可复盘、可继续扩展的技术资产。没有公开证据支撑的细节继续留在私有材料池,不进入线上页面。
公开版深化
案例定位
虚拟形象 Unity → Three.js 迁移不是孤立笔记,而是虚拟人技术能力下的一个可复用案例。它服务于“性能治理与稳定性优化”这条主线,公开版重点保留问题抽象、工程取舍和可复用方法,不暴露内部系统细节。
关键问题
主导 B 站虚拟形象从 Unity WebGL 到 Three.js 的技术选型与迁移,解决 WebGL 在移动端的性能天花板。
这篇文章已经覆盖 背景、技术选型:为什么选 Three.js、迁移过程、结果、教训。后续阅读时应重点看三件事:问题如何被定义,方案如何在约束下落地,以及哪些经验可以迁移到下一次类似项目。
企业级产出
| 产出 | 公开表达 |
|---|---|
| 问题定义 | 用用户体验、性能、稳定性或交付效率描述影响 |
| 技术方案 | 保留架构、流程、算法和工具链层面的抽象 |
| 指标证据 | 只使用页面已有数字或经过脱敏审查的量级 |
| 复用方法 | 沉淀为 SOP、检查清单、图谱关系或后续案例链接 |
指标与证据
- 机型覆盖率 30% 目标 90%+
- 启动速度 慢(10s+) 快(< 3s)
- 包体积 大(10-20MB+) 小(< 2MB JS)
- 骨骼动画映射验证:抽检 20 个动画确保无变形
复盘结论
这个案例的核心价值,是把一次具体工程处理沉淀成可检索、可复盘、可继续扩展的技术资产。没有公开证据支撑的细节继续留在私有材料池,不进入线上页面。