关于 spine 在原生平台上无法合批的问题,代码定位在 getIndexOffset 导致的断批

  • Creator 版本:3.8.5 (3.8.6 更严重)
  • 目标平台:iOS / Android
  • 重现方式:编译出安卓应用,点击问题重现
  • 重现概率: 100%
  • 备注:3.8.5还能够重组合批,3.8.6是无法合批了

关于 spine 在原生平台上无法合批的问题,代码定位在 getIndexOffset 导致的断批

这是一个老问题,发现论坛中已经有人提及没有人理会。重开一篇希望后续能够改善。

项目中使用 3.8.5 编译出的安卓应用,发现 spine 的批次爆了, web 开发期间一直都是好的啊。

经过日志加眼神发现 Batcher2d.cpp 的 drawInfo->getIndexOffset() == _currDrawInfo->getIndexOffset() + _currDrawInfo->getIbCount() 的判定出现了断批。

需要再进一步分析。

  1. spine 渲染合批逻辑,Batcher2d::handleMiddlewareDraw 是按照节点顺序依次获取 drawInfo 判断是否能够合批。
  2. spine 的 drawInfo 是由 MiddlewareManager::render 生成的。
  3. MiddlewareManager 有个函数 AddTimer 来添加 spine,然后调用 spine 的 render 生成 drawInfo 。
  4. AddTimer 函数再 spine 的 onEnable 和 onDisable 调用;另外一处是 spine.skeletonData = data 的时候进行设置。
  5. 所以如果你动态设置 skeletonData ,那么你将打乱 updateList,就会与节点顺序不一致。
  6. 3.8.6 用 map 设置标记,然后管理 updateList,导致不用动态加载就不能合批了。
  7. 由于 MiddlewareManager 的 updateList 顺序与节点顺序不一致,导致 IndexOffset 判定不能合批。

打乱 updatelist 前:
image

将部分节点 active 先设置 false 再设置 true,这样重置下节点顺序与 updatelist 不一致。
image
总结: 问题是发现了,在不修改引擎底层的前提,暂时的解决方案动态加载的 spine 放在地图节点的最上层。

3.8.6 的 MiddlewareManager 的 updateList 的处理方案使合批彻底废了。

晚点再想想看有没有更加合适的方案再分享。test.zip (209.7 KB)

1赞