3.15.1版本在android上突然点击无效

上个星期升级的3.15.1,在android上会不定时的出现注册的touchListener无效的情况,比如逻辑代码上注册了8个,结果真正派发时,队列里面只有3个了(注:java层那边没问题,事件都派发了)
我用的cocos2dx-lua,ndk-r11c,android-sdk api-19
我最早用的3.6,后来升级到3.11,期间遇到的bug都不是太严重,只有这次太奇怪,同一段c++代码在windows和ios上都ok,在android上不行了

能否基于cpp-empty-test创建一个重现问题的最简单demo,我们这里会迅速跟进。谢谢。

我之前遇到过类似的问题:UI线程阻塞了,导致touchListener无法响应。可以参考一下

https://github.com/cocos2d/cocos2d-x/issues/17989

github上也有人遇到这个问题

demo等我这几天有空我建立下,要复现我觉得应该很容易(按照我这边的游戏的表现)
1.建个空的工程,待会儿打包到android用
2.在舞台上放一个nodeA,再在这个node里面建10个空node,这几个子node都监听touch事件,然后过几秒再把nodeA移除
3.过几秒在重新重复2步骤,就有概率发现在点击屏幕派发事件时本来应该touchListener是10个的,结果可能只有3个了,在windows上ios上不会发生,在android上发生了

补充下,cocos的eventdispatcher那段c++代码我反复看了一整天,也没发现在不同平台下有不同处理的地方,而且都是同步派发,跟线程无关,所以感觉这个问题发生的让我特别无从下手,因为我是3.11升级上来的,我还特别对比了下个3.11的代码,感觉除了sort改成了stable_sort别的也没啥了,

3.15.1是否在别的地方有什么改动,影响了该块功能逻辑?

是openGLView的线程阻塞?

还是提供一下demo,我们会跟进。谢谢。事件派发这块逻辑应该很久没动了。

GL线程被阻塞的话,你画面都不会刷新(或者卡顿)

我之前遇到就是android UI线程卡住了,touchListener没反应,但GL继续正常渲染

对的,touch事件是从ui线程抛出的,如果UI线程卡住了,那么事件就无法抛到GL线程执行,表现就跟touch事件收不到一样。

我的问题是类似的 最近在3.15.1 版本android 上遇到 事件不可点击的问题,频繁出现,已注册的事件可以正常,后注册的事件失效

只有在android上出现么?

楼主快提供demo吧
我这边3.10升级3.15.1后在android也遇到了,ios没怎么测,所以不清楚,游戏运行着一段时间,面板上的按钮全都不能点了,点击时事件会穿透到场景中去,连着出了几次,后面准备查找原因又一直没法复现了。有时日志会不断输出:
debug info: Assert failed: _inDispatch should be 1 here.
…/CCEventDispatcher.cpp function:updateListeners line:1227
debug info: Assert failed: If program goes here, there should be event in dispatch.
…/CCEventDispatcher.cpp function:updateListeners line:1148
debug info: Assert failed: _inDIspatch should be 1 here.
…/CCEventDispatcher.cpp function:updateListeners line:1227
debug info: Assert failed: If program goes here, there should be event in dispatch.
…/CCEventDispatcher.cpp function:updateListeners line:1148
debug info: Assert failed: _inDIspatch should be 1 here.
…/CCEventDispatcher.cpp function:updateListeners line:1227
debug info: Assert failed: If program goes here, there should be event in dispatch.
…/CCEventDispatcher.cpp function:updateListeners line:1148

我也遇到了,断点进去,发现点击后在下面的if (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)后直接return了,后面的逻辑都没跑下去
出现的方式,可能是在出现这个按钮之前,代码做了把资源从包里解压出来的操作
难道是卡逻辑导致监听的东西没放到_listenerMap里面?

void EventDispatcher::dispatchTouchEvent(EventTouch* event)
{
sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);
sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);

auto oneByOneListeners = getListeners(EventListenerTouchOneByOne::LISTENER_ID);
auto allAtOnceListeners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID);

// If there aren't any touch listeners, return directly.
if (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)
    return;
bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);

const std::vector<Touch*>& originalTouches = event->getTouches();
std::vector<Touch*> mutableTouches(originalTouches.size());
std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());

我也碰到这个问题。
我的问题是:
android第一次进游戏后,不能点击,任何地方都点击不了,动画之类还在播放;
大部分手机退出,第2次进去就正常了,但有些手机后面进去也不行。
win32上没问题。
觉得莫名其妙,把cocos文件夹下换回到3.14或3.10就好了,没有试,不知道3.15是不是好的。

估计是不是在多线程环境下调用了FileUtils::getContents?
参考一下这个帖子:

https://github.com/cocos2d/cocos2d-x/issues/17989

pthread_self() 在FileUtilsAndroid::getContents里面打印一下线程id,看看是否有不同线程访问。
如果有,再把以下一行注释试试看。

FileUtils::Status FileUtilsAndroid::getContents(const std::string& filename, ResizableBuffer* buffer)
{
//把这行注释掉试试看 Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(EVENT_BEFORE_READ_FILE);

确实是有多线程调用,注释了就没问题了……
那么,更加妥当的处理方式是怎么来搞?

因为EventDispatcher本身不是线程安全的,更加稳妥的方案需要先明确为什么会在多线程环境下调用此API。
你游戏层会显式在多线程环境下调用FileUtils::getContents API么?

在游戏启动过程,我起了一个线程调用FileUtils::getContents将包内资源解压出来
核心点是读取资源,而非进行Event Dispatch

在以往版本使用过程中,这个接口没有跟线程或event挂钩,更多像是一个简单的读取功能
由调用者外部去确保线程安全即可

我不知道3.15这个版本为何要在这里去塞进事件代码
如果在FileUtils::getContents调用前去dispatch Event是否更为妥当
大一统的在getcontents中去一刀切dispatch,感觉不太合适

了解,如果是这样,还是不通过派发事件的方式吧,按照我发的issue里面的开发者的方案,直接通过一个函数去设置即可,游戏层基本也不会需要监听这个事件的。我稍后提交一个Pull Request修复这个问题吧。

你是说 使用EngineDataManager::onBeforeReadFile(NULL); 来代替?
接下来是会出3.15.2的版本
还是我们自行修复?

现在用的是3.13.1,但更新到3.15.1是准备做项目稳定性测试了