解决 SPINE 骨骼混合动画错乱问题

Spine 是一个很好的制作 2D 骨骼动画的软件,其中提供的混合 (mix) 动画功能可以很柔和过度两个不同的动画,但在混合时期,稍有不善,非常容易出现各种错乱。在 Spine2D 骨骼动画群上,有人提出全 K 帧、K 透明轴等等方法,这些方法往往只是恰好解决了一些问题,但还有相当一部分潜在的问题还是可能发生的。


1. 问题原因

在使用过程中,我发现 Spine 的错乱问题主要表现在以下两个方面:

  1. Slot 位置下,A 动画中有 abcd 四个时间轴,而 B 动画只有 abc 三个时间轴,那么从 A 切换到 B 时,切换时 d 轴的状态(纹理或色彩)可能会残留到 B 动画上(如 A 是攻击动画,B 是行走动画,d 是特效轴)。如果是制作叠加动画(会同时播两个动画,比如边跑边打),那么可能不需要全部补齐,这种要视需要而定。
  2. Slot 位置下,A 动画与 B 动画混合时期(●表示关键帧):

    A:●—————————●——
    B:        ●——————————

              | 混合时期 |

  在这种状态下,由于 B 动画设置了纹理之后,A 动画又设置了纹理,混合时间之后,Slot 位置下的纹理是 A 动画的纹理,这时候纹理错乱了,这种不能通过 K 帧解决,因为需要注意的问题太多了。

2. 如何解决

如果以上两个问题都解决了,那么混合动画基本就没有什么问题了(目前我项目中还没有发现其它问题)。

  • 对于问题 1,原则上,A 动画有的轴,B 动画也必须中,如果 B 动画中没有,则自动为 B 动画以 setup pose 状态为基准生成这条轴(纹理、变换、色彩等)。补齐及二制作转换脚本请见Github

  • 对于问题 2,修改 spine-runtime 中的 Animation.c 文件中函数 _spAttachmentTimeline_apply 中的代码:将 “if (self->frames[frameIndex] < lastTime)return;” 改为 “if (self->frames[frameIndex] < lastTime && 1 - alpha <= FLT_EPSILON) return;”, 并且在文件开始部分添加 “#include <float.h>”。alpha(0~1)参数表示是混合进度,原理很简单,在混合时期一直让新的动画轴去设置纹理。