同屏几百个 Spine 实例时,官方 sp.Skeleton 在中低端机上扛不住,所以做了一套 Spine → VAT 的方案,这里分享一下真机测试数据。
思路
- 离线烘焙 :用引擎自带的 Spine 4.2 运行时逐帧跑动画,把 最终顶点 (已经算完骨骼、形变、约束、剪裁)按「固定槽位」写进浮点贴图,颜色和透明度另存一张 8 位贴图。
- 运行时 :只剩一个 shader 按时间采样贴图取顶点,CPU 每帧只推进播放时间,不再算骨骼。帧间在 VS 里插值,低帧率烘焙也平滑。
-
两个组件 :
- 2D:走 UI 合批,能和 Sprite、
sp.Skeleton按兄弟节点顺序穿插和遮挡。 - 3D:继承 MeshRenderer,走 GPU Instancing。
- 2D:走 UI 合批,能和 Sprite、
- 支持的特性 :剪裁(clipping)在 GPU 上做,多种混合模式、事件回调、挂点(socket)也都支持。
- 不支持的 :运行时换装、动画混合(crossfade)、实时改骨骼,这些都得在烘焙时定好。
测试条件
- 引擎 :Cocos Creator 3.8.7,Spine 4.2
- 手机 :天玑 700(6×2.0GHz + 2×2.4GHz),1080×2400
- 资源 :项目里的 Spine 角色,每个实例约 990 个三角形,含剪裁,3 段动画
-
对照 :官方
sp.Skeleton,SHARED_CACHE模式 -
debug 包 :构建面板勾「调试模式」,gradle
assembleDebug -
release 包 :不勾「调试模式」,gradle
assembleRelease(native -O2)
测试方法:
- 每个实例一个节点,
addComponent后赋值skeletonData,都是正常的业务写法。 - 实例数分 30 / 150 / 600 三档,每档轮换 4 种模式,每个阶段跑 20 秒。
- 每个阶段从第 6 秒开始,读 10 秒
/proc,得到 App 进程 CPU 时间占整机 CPU 时间的比例;帧率和 DC 取引擎自己的统计。
四种模式:
- 2D 插值 :2D 组件,帧间插值。
- 2D 阶跃 :2D 组件,不插值,逐帧跳。
- 3D 插值 :3D 组件,帧间插值。
-
官方 :
sp.Skeleton的SHARED_CACHE模式。
帧率(fps / 帧间隔 p95,ms)
实例 模式 debug release
--------------------------------------------------
30 2D 插值 60.2 / 16.9 60.2 / 17.2
30 3D 插值 60.2 / 16.9 60.1 / 17.4
30 官方 23.9 / 49.3 60.1 / 17.0
150 2D 插值 60.3 / 16.8 60.2 / 16.9
150 3D 插值 60.2 / 16.8 60.2 / 16.9
150 官方 6.2 / 203.1 60.2 / 16.8
600 2D 插值 60.2 / 16.8 60.1 / 16.8
600 3D 插值 59.9 / 16.8 60.2 / 16.8
600 官方 2.1 / 711.7 24.4 / 48.0
CPU(App 占整机 8 核的 ;括号里是 top 口径,100 = 占满 1 个核)
实例 模式 debug release
-----------------------------------------------------
30 2D 插值 15.7%(126%) 10.9%(87%)
30 3D 插值 15.7%(126%) 10.3%(82%)
30 官方 16.8%(134%) 12.4%(99%)
150 2D 插值 15.7%(126%) 9.3%(74%)
150 3D 插值 15.5%(124%) 8.9%(71%)
150 官方 15.0%(120%)* 16.8%(134%)
600 2D 插值 16.1%(129%) 11.1%(89%)
600 3D 插值 16.5%(132%) 10.6%(85%)
600 官方 14.0%(112%)* 18.1%(145%)
- 官方这两档在 debug 下只有 6fps 和 2fps,每秒算的帧少,CPU 占比反而低,不能拿来直接比。
Draw Call
实例 2D 3D 官方
---------------------------
30 3 6 107
150 8 6 530
600 23 6 1956
(release 数据。debug 包每项多 2 个 DC,应该是左下角那个性能统计面板。)
- 3D 组件用 GPU Instancing,DC 不随实例数增长。
- 2D 组件每 48 个实例合一批,DC 按实例数线性增长,好处是能和 UI 正常穿插、遮挡。
内存
- 引擎统计的 GFX 纹理:VAT 18.7 MB,官方 16.0 MB。多出的 2.7 MB 就是 VAT 数据贴图(position 用 32 位浮点)。
- 进程 PSS 这次没法公平比:几种模式在同一个进程里按顺序跑,两套资源一直常驻,越往后读数越高。要得到准确数字,得每种模式冷启动各测一次,这次没做。
结论
- release 下 :
- 官方
SHARED_CACHE150 个实例还能稳住 60 帧,但 CPU 已经比 VAT 高一截,600 个就掉到 24fps。 - VAT 在 600 个实例时还是 60 帧,CPU 基本不随实例数增长:约 9%~11%,也就是不到 1 个核。
- debug 下 :
- 官方 Spine 掉得非常厉害:30 个实例就只有 24fps,600 个只有 2fps。debug 包的 native 代码没开优化,而官方 Spine 的逐帧计算都在 native 侧。
- VAT 每帧几乎不做计算,debug 下照样 60 帧。
- 所以评估 Spine 性能 一定要用 release 包 ,debug 包会严重低估官方 Spine。
- 代价 :多占几 MB 显存,而且放弃运行时的灵活性,包括换装、crossfade、改骨骼。适合同屏大量重复、动画固定的 Spine,比如背景人群、特效小人。
有问题欢迎交流~