尝试按帧观察粒子发射器Action 方案1:Application::run() 第1帧最近在Cocos2d-x使用Effekseer的3D粒子时遇到了发射器的Action被延迟一帧执行的问题,我把该问题分析与解决过程写成了本文。
- 执行AppDelegate::applicationDidFinishLaunching()
- 执行场景init方法。
- play粒子。
- 设置每帧触发的粒子update。
- 执行场景init方法。
- 执行Director::drawScene()
- 执行pollEvents。因此出现了黑色窗口。
- 执行_scheduler->update。第一次update,本次update不会调用粒子update。
- 离开Director::drawScene()。因此画出了第一帧画面,此时没有出现粒子
- 执行_scheduler->update。执行第1次粒子update。
- 本帧绘制,无粒子出现。(粒子呈现的不对,正确情况是本帧应该出现起始位置的粒子)
- 执行_scheduler->update。执行第2次粒子update。
- 本帧绘制,粒子出现在起始位置。(粒子呈现的不对,慢了一帧)
- 执行场景init方法。
- 手动执行第1次粒子update。也可不手动执行,没影响到绘制效果。
- 本帧绘制,无粒子出现。
- 执行_scheduler->update。执行第2次粒子update。
- 本帧绘制,无粒子出现。(粒子呈现的不对,正确情况是本帧应该出现起始位置的粒子)
- 执行_scheduler->update。执行第3次粒子update。
- 本帧绘制,粒子出现在起始位置。(粒子呈现的不对,慢了一帧)
EffectEmitter执行update方法时,获取自己的世界矩阵,放到自己引用的EffectManager里(是在自己Node的update方法之前执行的)。
auto transform = this->getNodeToWorldTransform(); manager->setMatrix(handle, transform); cocos2d::Node::update(delta);
其中,EffectManager执行setMatrix方法时:通过发射器传入的handle获取到drawSet,矩阵设置到drawSet里的矩阵(通过manager2d)。
EffectManager执行update方法时,即manager2d执行update方法,会遍历了每个drawSet,使用了drawSet里的矩阵。
解决问题删除源码中的发射器scheduleUpdate。在每一帧manager的update之前,手动调用发射器的update,才能确保发射器比manager先执行update。
发射器update中,把自己的视图矩阵传给了manager。manager的update里会获取的发射器视图矩阵。在之前错误的顺序中,manager的update执行时,存的视图矩阵都是上一帧的。
由于我是直接改动了代码使用方式,也就是把源码里发射器的scheduleUpdate给删了,手动在外部执行发射器的update的。这种改动较大,与官方文档对于外部使用的说明差距较大,所以我没有在github向官方库提pr,而是提了issue,希望他们能在文档里注明update的执行顺序。
在github向官方库提的issue:
Scheduler Update method order · Issue #34 · effekseer/EffekseerForCocos2d-x · GitHubHello. In one frame, EffectEmitter Update method need to be called before EffectManager Update method. Otherwise, the Node property(position...) of the particle being rendered is last frame not current frame. I think the Update method or...https://github.com/effekseer/EffekseerForCocos2d-x/issues/34
本文链接:https://blog.csdn.net/cafecc/article/details/122547870



