Replace Scene problem - child not found!

I am replacing one of my scenes from callback function using:

Director::getInstance()->replaceScene(TransitionFade::create(0.5, MyScene::create()));

It replaces scene, but without transition… and Visual Studio console show the following:

cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!
cocos2d: removeChildByTag(tag = -86050082): child not found!

I also tried to replace scene from Update function… still the same effect – no transition. Tried to make it via RunAction:

runAction(CallFunc::create(CC_CALLBACK_0(AnotherScene::gotoMyScene, this)));

and inside gotoMyScene is the same Director::getInstance()->replaceScene(TransitionFade … but it still changes scene without transition, and shows child not found.

Note, that if I replace scene from Keyboard handler, then everything works as expected. What I am doing wrong?

Resolved! The problem was - that I was calling: Director::getInstance()->replaceScene(... multiple times from update(float dt) function. Apparently this is not supported scenario, and care should be taken to not call replaceScene with transition multiple times, without waiting for transition to complete.

How did you solve the problem since you cannot run it from update? I have the same issue but I have to be able to run it from update or similar.

You want to replace a scene with another scene in update()? update runs every frame…

Nothing is stopping you from calling replaceScene() from update, but as slackmoehrle pointed out, it will run every frame, so you need to ensure it’s only called once.

For instance:

class YourNode : public cocos2d::Node
{
...
private:
    bool enableTransition = false;
};

void YourNode::update(float delta)
{
    if (this->enableTransition)
    {
        this->enableTransition = false;
        
        auto newScene = Scene::create();
        Director::getInstance()->replaceScene(newScene);
    }
}

So, when you need to do the transition, set the ‘enableTransition’ bool to true, so on the next update it starts the transition, and set ‘enableTransition’ to false, and won’t re-enter that condition.

If you don’t want to wait till the next update to do the transition, then there are other ways to handle this.

1 Like

Thanks. Yes, I am already ensuring one call from within the update function:

void HelloWorld::update(float dt){

if ( mySprite->bContact == true ){
    mySprite->bContact = false;      
    auto newScene = this->createScene();
    Director::getInstance()->pushScene(TransitionFade::create(4.5, newScene, Color3B(0, 0, 0)));
}

}

But I still get the error:
cocos2d: removeChildByTag(tag = -86050082): child not found!

Have you put a breakpoint, and made sure the bContact isn’t setting back to true after the update call? …Or put a CCLOG/print and see if it is hitting true on each frame after the only intended one. If so, I like @R101 example of making a unique variable for this, not another variable that may be reset elsewhere.

-86050082 is a strange number, so converting it to hex leads to this: 0xFADEFADE

Do a search in the code for FADEFADE, and guess what, you’ll end up here:

CCTransition.cpp:

const unsigned int kSceneFade = 0xFADEFADE;

Searching a bit more in the TransitionFade class, you’ll see this:

void TransitionFade::onExit()
{
    TransitionScene::onExit();
    this->removeChildByTag(kSceneFade, false);
}

You may want to put a breakpoint on that, and ensure that kSceneFade is actually still valid at that point. It’s really hard to help you with this, since it’s your code, and it’s really up to you to step through with a debugger to trace down the source of the issue.

2 Likes

That may not be a good idea. Are you 100% certain that mySprite->bContact is not being reset to true, or that mySprite is still valid? If mySprite is freed, but not set to nullptr, then bContact would be a read from a random memory location that may contain different data, and that may make the condition true again. Just throwing ideas out there.

@tdebock pointed out exactly what you should be doing, which is using CCLOG and breakpoints to narrow down your search for the source of the problem.

1 Like