+7 votes

Hi,
I am fairly new to the Godot Engine and playing around with it for some days. What I have seen so far is totally awesome and I'am really impressed how great Godot is.

However I stumbled over a little misunderstandig regarding overriding base functions. My program has a base script for every item called "base_item.gd". It holds some basic functions for clicking on the item, moving it around and stuff like this. For example:

extends StaticBody2D

func _ready():
    set_process(true)
    do_stuff()

func _process(delta):
    do_more_stuff_often()

Now I created a new Scene and attached a script which inherited the other script:

extends "base_item.gd"

func _ready():
    do_different_stuff()

In my understanding this should override the "original" ready function. Therefore, neither "dostuff()" nor the "_process()" function should be called. However, in my program all three functions are called, similar to what you would observe if you call a super()-function in python.

In contrast, if I create a new "do_stuff()"-function in the new script only the new function is called. I therefore expect that the base functions like _ready() and _process() always call something like a super() function.

My question is: Is there a way to prevent that the parent base functions are called?

Best,
lbcp

in Engine by (22 points)

1 Answer

+12 votes
Best answer

As far as I understood the source code of Godot, it looks like these callbacks are called with "multilevel", which means all overrided functions will forcibly be called in cascade, bypassing manual calls to the base with "._ready()" like super() would do in other languages.

node.cpp

    case NOTIFICATION_READY: {

        if (get_script_instance()) {

            Variant::CallError err;
            get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_ready,NULL,0);
        }

While it looks handy at first, I think that it's not a good choice at all, because it basically prevents you from doing that choice.

There is a workaround: this will happen for some functions called by the engine, but not for functions you created yourself. So you can do something like that instead:

Base script:

# This is the only place you will use _ready()
func _ready()
    _on_ready()

# Custom function that you will be able to override
func _on_ready()
    # Do base stuff
    set_process(true)
    do_stuff()

Script inheriting the base:

func _on_ready():
    # Do inheriting stuff
    do_different_stuff()

    # And if you still wish to call the base code
    # in the order you want, you can do this (notice the dot):
    # ._on_ready()
by (27,648 points)
selected by

Thank you very much for your fast and answer. I was expecting something like that.
I will adapt my scripts so that all unique declarations and calls are in custom functions. Thanks again!

And looks like the order in which functions are called is not always the same (like ready vs process) but this forced autocall may change on Godot 3.

Yeah, it is either reversed or forward the class hierarchy. Removing that in 3.0 sounds great. When/where was this discussed? Is there a Github issue about that?

Got this recently from Juan:
https://twitter.com/reduzio/status/789180964798803968

And a discussion about it on GH:
https://github.com/godotengine/godot/issues/6500

I think that current behavior is source of many problems related to initializations, I hope to see it changed as it is on most of the engines (at least forced super call but no implicit).

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.