coo-skel-baker | 骨骼动画优化实践

最近把自己用的骨骼动画烘焙与 GPU 播放方案整理成了 coo-skel-baker 插件。这里分享一下实现思路、测试结果。

先看效果

完整演示包含 Playback、Events、Sockets、Features,以及 2D / 3D 各 10000 个动画单位实测

https://www.bilibili.com/video/BV1Bzsd6nEBD/

播放路径 测试角色 单位数 视频中 Stats FPS Draw Calls
2D UI 合批 Spineboy 10000 60 4
3D GPU Instancing Hero 10000 60 14

1. 把实时解算换成离线采样

核心不是把整套 Spine Runtime 搬到 GPU,而是提前计算运行时不再需要改变的部分:

Spine JSON / SKEL + Atlas
  → 编辑器使用匹配版本的官方运行时采样
  → 烘焙数据:骨骼矩阵、绘制数据、事件、挂点等
  → CPU 更新时间、队列和实例参数
  → GPU 读取数据纹理,恢复顶点并插值

基础蒙皮数据保存采样后的骨骼矩阵,Shader 根据播放时间读取相邻采样帧,并对恢复的结果做插值。

所以它省掉的主要是每个角色每帧的实时 Spine 解算和 CPU 蒙皮,不是让 CPU 完全不工作。事件分发、挂点更新、组件管理、渲染提交仍然有少量成本。

烘焙采样率不等于运行帧率:30 FPS 采样可以在更高运行帧率下插值播放,但插值不等价于重新求解原始曲线和约束,快速动作与循环接缝仍要对照检查。

2. 2D 合批与 3D 实例化是两套问题

2D 路径使用 SkbAnimation组件,接入 UIRenderer。烘焙动画与 Sprite、Label 交错时,仍要遵守 UI 顺序;材质、贴图、混合状态、遮罩或缓冲条件不一致,都可能拆批。多页图集和不同混合模式也会增加批次。

3D 路径使用 SkbAnimation3D组件,在资源、材质和绘制范围匹配时,通过 GPU Instancing 提交各实例的变换与动画参数。适合把平面骨骼角色放进 3D 场景,也提供 Billboard;它不会把 Spine 角色变成立体模型,透明排序和填充依然需要注意。

两条路径都不意味着“所有素材固定一个 Draw Call”。我更关心的是:在保持正确画面和顺序的前提下,能共享多少资源、减少多少 CPU 工作。

3. 事件与挂点

动画时间轴事件随数据一起烘焙,播放端按经过的时间区间触发回调;挂点则保存指定骨骼的采样变换,运行时读取并驱动目标节点,适合枪口、武器和特效节点跟随。

这和重新执行完整骨骼解算不同。挂点越多、每帧更新的目标节点越多,CPU 成本也会增加。

4. 如何接入使用

插件负责源文件烘焙和运行时模块安装。

作者建议

适合割草、群体单位、大量实例展示等场景;也适合多版本 Spine 资源统一烘焙后的播放(就是多版本spine混用)。

如果项目依赖运行时 IK、复杂多轨混合、动态新增附件或实时物理驱动动画,不建议直接替代官方 Runtime。

插件页面:coo-skel-baker | 烘焙骨骼动画GPU播放组件