Can I override the _ready() and _process() functions in child classes?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By lbcp
:warning: Old Version Published before Godot 3 was released.

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 “do_stuff()” 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

:bust_in_silhouette: Reply From: Zylann

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()

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!

lbcp | 2016-10-23 13:53

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.

eons | 2016-10-23 18:40

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?

Zylann | 2016-10-23 19:47

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

And a discussion about it on GH:
Gdscript: It's impossible to override _process function · Issue #6500 · godotengine/godot · GitHub

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).

eons | 2016-10-23 23:28