[已解决]骨骼动画播放完毕回调有时不执行。

最近研究到骨骼动画了,发现了很多的问题。比如对于新编cocos stduio2.3.3导出骨骼动画来讲,最终加载出的骨骼动画是ActionTimeline类型的。
ActionTimeline有一个方法:setAnimationEndCallFunc(),注册后在动画每一次播放完毕后,会回调指定的callback方法。
但经实测,此回调方法并不是每一次都执行的!

关键代码如下:
FileUtils::getInstance()->addSearchPath(“bone_animations”);
cocostudio::timeline::SkeletonNode* skeleton = (cocostudio::timeline::SkeletonNode*)CSLoader::createNode(“bone_animations/Skeleton.csb”);
skeleton->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
skeleton->setTag(1);
//加载资源文件中的骨骼动画
timeline::ActionTimeline *at = CSLoader::createTimeline(“bone_animations/Skeleton.csb”);
at->play(“animation0”, true);//找到名为“animation0”的动画,设置为循环
//对cocos studio中已经记录的帧事件,会引起以下回调
at->setFrameEventCallFunc(CC_CALLBACK_1(HelloWorld::onFrame, this));
at->setAnimationEndCallFunc(“animation0”, CC_CALLBACK_0(HelloWorld::onPlayEnd, this));

skeleton->runAction(at);//骨骼对象运行骨骼动画

回调方法:
void HelloWorld::onFrame(cocostudio::timeline::Frame * frame)
{
琀椀洀攀氀椀渀攀::EventFrame * eventFrame = (timeline::EventFrame *)frame;
//获得当前事件帧的事件名
猀琀搀::string strEvent = eventFrame->getEvent();
椀昀 (strEvent == “cut_begin”)//如果当前事件为开始劈下

氀漀最(“cut_begin”);//刀开始劈下时输出"cut_begin"

}
void HelloWorld::onPlayEnd()
{
氀漀最(“cut_end”);//动画播放结束后会输出"cut_end"
}

但经过调试输出结果发现,动画结束回调并不会每一次都执行:
cut_begin
cut_end
cut_begin//连续2次没有执行动画结束回调方法
cut_begin//连续2次没有执行动画结束回调方法
cut_begin
cut_end
cut_begin
cut_end
cut_begin
cut_end
cut_begin//此处没有执行动画结束回调方法
cut_begin
cut_end
cut_begin//此处没有执行动画结束回调方法
cut_begin
cut_end

请问怎么解决啊。。。
另外,我把setAnimationEndCallFunc这种,换成了骨骼动画最后一帧添加帧事件的回调,一样是上面的结果,不会每次都执行。。。

以前遇见过类似的问题,和你的一模一样。
当时,他是在studio中设置帧设置有好几个“begain”。
你可以检查下你的studio编辑过程,或者使用test工程里面的骨骼动画测试一下,

另外,你的引擎版本用的多少?

ps:如果最后还有问题,加我QQ:3094485951

这个不是的,因为我是在给骨骼动画中的“刀”绑定“拖影”MotionStreak时发现的问题。确实是"cut_end"有时不会被调用,导致我在里面写的代码不起作用,而引起的拖影的不正常。
另外,我刚又检查了一遍,确实是只有一个"cut_begin"的帧事件。
cocos studio版本是2.3.3。cocos2d-x版本是3.9RC0。

之前我也遇到过同样的问题,不过是因为当时那个动画只有一帧的时候就比较容易出现
后来将那动画改成两帧就好了

我那个动画一共设定了120帧。。。

我自己暂时这么解决了:
我的骨骼动画时间比较长,一共120帧。
然后我增加1帧,动画变为121帧。给120帧(原来的最后一帧)设定帧事件"cut_end"。
然后不用setAnimationEndCallFunc,只用setFrameEventCallFunc,在帧事件回调中测试:
void HelloWorld::onFrame(cocostudio::timeline::Frame * frame)
{
timeline::EventFrame * eventFrame = (timeline::EventFrame *)frame;
//获得当前事件帧的事件名
std::string strEvent = eventFrame->getEvent();
if (strEvent == “cut_begin”)//如果当前事件为开始劈下
log(“cut_begin”);
else if (strEvent == “cut_end”)//如果当前事件为劈下结束
log(“cut_end”);
}
然后就完全没问题了!

结论,应该是最后一帧的回调响应机制有问题,有时候会跳过最后一帧的回调方法。
所以,我这个解决方案就是再增加1帧,倒数第2帧作为动画播放完毕的关键位置。。。

之前有人报过这个问题 楼主可以看看这个修复: https://github.com/cocos2d/cocos2d-x/pull/12040/files

晕,至少半年前都有人发现而且给出了解决方案,那最新版的cocos2d-x为啥没加进去啊……

我也遇到这个问题,根本就进不了最后一帧的处理事件;看https://github.com/cocos2d/cocos2d-x/pull/12040/files ;它_currentFrame没有等于我刚刚设置的帧处理事件的位置