Director::getInstance()->getRunningScene() returns NULL

Hi this is my code
Note that I am calling the code in bool Layer init()

bool RunningGameScreen::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    this->disableGravity();
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto background = Sprite::create("Floor.png");
    float scaleX = visibleSize.width / background->getContentSize().width;
    float scaleY = visibleSize.height / background->getContentSize().height;
    background->setScale(scaleX, scaleY);
    
    background->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));

    this->testingArea();
    return true;
}
void RunningGameScreen::disableGravity()
{
    auto scene = Director::getInstance()->getRunningScene();
    scene->getPhysicsWorld()->setGravity(Vec2(0.0f, 0.0f));
}

But when getRunningScene returns NULL , any idea why it is failing there?
I am using Cocos2d 3.9 on Windows 10 64 bit

1 Like

Does it return NULL if you try calling it in init() as a test?

Yes it does.

I would think this is a bug…it does seem like it should return properly.

Hmm , just to make sure it is not issue not at my end. Because I think most people would have reported it as of now had that be case.

Yeah, let me try a quick test in a cocos new project.

Thanks @slackmoehrle. Let me know I am waiting.

So I tried 2 tests. One in AppDelegate and one in init() and both return NULL

If this is true, I would say something is broken. @ricardo, do you see that we are doing anything wrong?

Hmmm that is quite bad I would rather say, I guess one more reason to add unit testing or something like that. Anyhow what is solution should I downgrade to 3.7 something?

let us have @ricardo chime in here.

I will go test this in v3.8 and v3.7 too. I am using v3.9 currently. I should also test this in the latest in GitHub.

what is RunningGameScreen ? A scene ? Node? something that should be a part of a Scene?

If RunningGameScreen is a Node (or subclass) that is going to be part of the very first scene, then getRunningScene will return nullptr because there is no running scene at that point.

@slackmoehrle
runWithScene() is not an immediate operation. It will take effect on the next frame. getRunningScene returns the current running scene, and not the one that is scheduled to run in the next frame.

RunningGameScreen is Layer . I am using a boilerplate code that is part of HelloWorld

But if in AppDelegate we call Director::getInstance()->runWithScene() then shouldn’t technically that getRunningScene should that scene itself?

[Edited out] Ricardo answers below.

getRunningScene() returns the current value of the _runningScene ivar.

runWithScene will schedule a Scene, and that Scene will be run in the next frame. And that is when the _runningScene will get updated.

Use node->getScene() to get the Scene that controls your layer.

Thanks for responding, so according to you getRunningScene only works once a frame has been output right and before that first frame method won’t work and proper way to get it is to use node->getScene()

short answer: yes.

long answer: no. getRunningScene always work. The thing is that runWithScene() does not immediately run a scene. So there is no running scene right after calling runWithScene()… you have to wait one frame.

node->getScene() returns null as well
I use this->getScene() this returned null. I think that first frame issue may be the reason as well in this case as well.

Node::getScene() is different. It will return the root node of the hierarchy dynamically cast as a Scene. So if a Node has been added to a hierarchy that has a Scene as it’s root then getScene() will return that scene object regardless of whether it’s running or not. As Node::addChild() is immediate, this function will always return what you expect.

Scene* Node::getScene() const
{
    if (!_parent)
        return nullptr;
    
    auto sceneNode = _parent;
    while (sceneNode->_parent)
    {
        sceneNode = sceneNode->_parent;
    }

    return dynamic_cast<Scene*>(sceneNode);
}
1 Like