replaceScene()とEventListener
普段、cocos2dxで開発している訳ではなく、あまりcocos2dxを知らないのだけれど、少し疑問が湧いたのでそれを書いてみる。
疑問: replaceScene()したあと、それまでに登録していたEventListenerはどうなるのか
例えば、あるシーンをタッチすると次のシーンに移る、というようなことをしたいとき
次のように書くことが出来ると思う。
bool AScene::init() { // ... auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = [this](Touch* touch, Event* event) { Director::getInstance()->replaceScene(AnotherScene::create()); } this->getEventDispatcher()-> addEventListenerWithSceneGraphPriority(listener, this); // ...
画面をタッチして次のシーンに移ったあとでもEventDispatcherに登録しているEventListenerは
EventDispatcherの中にまだ残っているのではないかと思う。
replaceScene()するときには手動でEventListenerを削除しないといけないのかなと思いながら
documentを読んでみるとちゃんと書いてた。
EventDispatcher Mechanism | Cocos2d-x
One more thing to keep in mind: if you add a _fixed priority_ listener to a node, you need to remove the listener manually when the node is removed. However, in the case of a _scene graph priority_ listener, the listener is bound to the node: when the node's destructor is called, the listener will be removed automatically.
document曰く、addEventListenerWithFixedPriority()を使う場合、Listenerに対応させたいNodeを削除するときに手動でListenerを消してね。addEventListenerWithSceneGraphPriority()を使う場合はListenerとNodeは対応しているので、Nodeのデストラクタが呼ばれるときに自動的にListenerも削除されるよ。
ってことらしい。なるほど。
上の例でいくとおそらく、replaceScene()をするとASceneのデストラクタが呼ばれ、そのタイミングでASceneに対応づけられたListenerが破棄されるという感じなんだろう。
Nodeの実装を見てみると確かにNodeのデストラクタでEventListenerを削除していた。
https://github.com/cocos2d/cocos2d-x/blob/v3/cocos/2d/CCNode.cpp#L207
_eventDispatcher->removeEventListenerForTarget(this);
ただ、replaceScene()を呼んだからといってすぐにASceneのデストラクタが呼ばれる訳ではないような気がするけど
その辺りはcocos2dxのGCが上手くやってくれているのだろう。
終わりに
今回思ったのは、欲しい情報にヒットするdocumentをすぐに探せるかはわからないんだけど
documentは読みましょうということでした。自分のフローにしておかねば。