转载

cocos2d-x 3.4 lua 触摸 BUG

  • 本站文章除注明转载外,均为本站原创或者翻译。
  • 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商;
  • 本站部分原创和翻译文章提供markdown格式源码,欢迎使用 文章源码 进行转载;
  • 本文标题:cocos2d-x 3.4 lua 触摸 BUG
  • 本文链接: http://zengrong.net/post/2247.htm

查看所有 quick 移植到 cocos2d-x lua 的文章

在 移植 quick2.2.3 的项目到 cocos2d-x 3.4 lua 中提到,我已经开始使用 cocos2d-x 3.4 lua 来开发目前公司的两个项目。

在这两个项目中,我将 cocos 的 lua 框架、quick 的 lua 框架和我自己开发的 lua 代码,全部整合到了我的 lua 项目 中。

下面提到的 quick 框架,都是指的我整合的这个 lua 项目。

问题描述

使用 cocos2d-x 3.4 lua + quick 框架进行开发的时候,发现对于销毁再重建的按钮来说,有超过 30% 的几率无法响应触摸事件。

为了方便重现问题,我使用 quick 框架提供的 cc.ui.UIPushButton 做了测试。下面这段代码中 testUIButton() 方法会创建一个按钮,每次点击这个按钮时调用 newUIButton() 方法,这个方法销毁前面创建的按钮,然后再新建一个按钮。

这个新建的按钮,相当大的几率会出现无法响应触摸事件的情况。

function TestScene:ctor()  self:testUIButton() end function TestScene:testUIButton()  self._bi = 0  cc.ui.UIPushButton.new('normal.jpg')   :setButtonSize(240, 60)   :onButtonClicked(function(evt)    self:newUIButton()   end)   :align(display.LEFT_CENTER, display.cx, display.cy)   :addTo(self) end function TestScene:newUIButton()  if self._bi > 0 then   local name = 'btn'..self._bi   self[name]:removeSelf(true)   self[name] = nil  end  self._bi = self._bi + 1  name = 'btn'..self._bi  local x = math.random(200)  local y = math.random(200)  self[name] = cc.ui.UIPushButton.new('normal.jpg')   :setButtonSize(240, 60)   :addTo(self)   :align(display.CENTER,     display.cx - x, display.cy - y)  self[name]:onButtonClicked(function()   print('--------------- test '.. name)  end) end 

问题解决

用一个很简单的方法可以解决这个问题,修改 testUIButton() 方法,讲 newUIButton() 进行延迟调用即可:

function TestScene:testUIButton()  self._bi = 0  cc.ui.UIPushButton.new('normal.jpg')   :setButtonSize(240, 60)   :onButtonClicked(function(evt)    scheduler.performWithDelayGlobal(function()     self:newUIButton()    end, 0.1)   end)   :align(display.LEFT_CENTER, display.cx, display.cy)   :addTo(self) end 

但这是个恶心的解决方案。要知道具体的解决方案,就要知道这个 BUG 产生的原因。

原因分析

当然,我上面的实现方式也是很恶心的。在一个按钮响应事件中创建一个按钮,在真实项目中应该不会这样使用。

不过,这个代码只是方便重现问题。在我们实际的项目中,只要是销毁之后再重建的按钮,就可能发生这种情况。而且,不仅仅是按钮,只要是继承 Node 的对象,销毁之后再重建,都会出现这个问题。

咨询了 cocos2d-x lua 开发组的 阳光七月 ,才知道原来这还是个历史遗留问题:

阳光七月 16:15:52

销毁的时候那个node标记为已经移除了,如果再创建时指针一样的话会判断为旧的,不会被添加触摸处理

Jacky 16:16:37

但是我已经换了变量名称,这样也会导致创建出相同的指针么?

阳光七月 16:17:18

在C++层创建与变量名称没有相关性啊

阳光七月 16:17:38

内存释放后又重新分配,当然有可能使用同一块内存

Jacky 16:17:54

是的,而且在同一段代码中,这种情况比较容易发生?

阳光七月 16:18:49

还是有不小机率的

阳光七月 16:21:13

估计不改Node是不行了

Jacky 16:21:41

Node 在 quick 里面不是改过么?

阳光七月 16:21:57

之前是想尽量不改-x的代码,在外面挂一层触摸模块

阳光七月 16:22:04

3.3之后没有改了

阳光七月 16:22:47

以现在为基础的话,改动应该也不大

阳光七月 16:23:01

主要是在Node释放时要处理一下

Jacky 16:23:25

quick2确实是没有这个问题的。

Jacky 16:23:42

如果在 C++层面这么写,也会有这个问题么?

阳光七月 16:24:09

肯定没有的,因为之前触摸模块是Node的一部分,不可能有问题

阳光七月 16:24:15

3.3之后才分开的

阳光七月 16:27:29

现在3.3之后是在lua层面收到onCleanup消息再回到C++层面释放触摸模块的

阳光七月 17:16:46

现在就是绕了个弯,在lua端收到onCleanup消息时再调用removeTouchEvent,这样的联系实在是不牢靠,所以问题也多

阳光七月 17:52:40

嗯,或者可以改一下引用机制,在底层延时销毁,上层不需要考虑这个细节。不过这样也要改Node,我后面再评估一下

看来,只需要坐等 cocos2d-x lua 开发组来修改就行啦。

(全文完)

正文到此结束
Loading...