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

对的,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是准备做项目稳定性测试了

对的,用onBeforeReadFile函数直接代替,你把这个函数改为public,然后去掉第一个参数或者传nullptr即可。
这个函数内部只是设置一个状态量,不会产生线程竞争问题。

Patch:
https://github.com/cocos2d/cocos2d-x/pull/18165

收到,谢谢

升级到3.15.1需要注意的事项 MARK一下

搞这个问题搞了好久,似乎发现DispatchGuard这个类的析构有时候没有调用,内存泄漏了。导致这个_inDispatch会大于2 。然后一直无法响应事件

我的问题跟你的一模一样,你解决了吗??
关键该怎么绕过这个坑呢?

升级到3.15.1 果然遇到同样的这个问题了android 下面点击太久了 点击事件 包括按键事件都没有效果了,。

我这边是android 3.10 游戏触屏点击事件也出现问题,上层业务没发现什么异常,请问这些问题有修复吗?