Proper subclassing and function calls with class-files in GDScript

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By nooberdev

Following scenario:

  1. KinematicBody2D with attached script “Player.gd”.
  2. Classfile named “State.gd”. Gets instanced by Player.gd by preloading as variable “state” and calling state.new() on it.
  3. Classfile named “Substate.gd”. Gets instanced by State.gd the same way Player.gd did it with State.gd.

Player.gd delegates _input and _process computation to State.gd which in return delegates them to the Substate.gd by calling the corresponding functions and passing event/delta.

If I understand the docs correctly, I should be able to call functions within the instanced classes, yet I get errors like "Nonexistent function “func_name” in base Nil.

Here are code examples for better understanding what I am trying to do.

Player.gd

extends KinematicBody2D

onready var state = preload("State.gd").new()

func _input(event):
	state.handle_input(event)

func _process(delta):
	state.update(delta)

State.gd

onready var substate = preload("Substate.gd").new()

func handle_input(event):
	substate.handle_input(event)

func update(delta):
	substate.update(delta)

Substate.gd

var speed = 100
var velocity = Vector2()
var movement

func handle_input(event):
    # set variables for directions (up, down, left, right)
    # match event and set velocity according to it
    # assign movement to velocity.normalized() * speed

func update(delta):
    move_and_slide(movement)

From my understanding, this should work but I keep getting “nonexistent function” errors.
What is my mistake here or what have I misunderstood?

Note: you don’t need the onready in Player.gd.

Zylann | 2018-08-06 17:31

:bust_in_silhouette: Reply From: Zylann

I think it’s because you used onready in State.gd. onready is a shortcut for the initialization of the variable to be executed when _ready is called. However your states are not nodes, they are plain classes, so their _ready is never called because it’s a Node feature.
In fact, you don’t need to use onready at all, from the look of your code. It should work without when you use new.

Solved the problem. thanks!
I still have to figure out how to call move_and_slide() from within the substate. any idea how? my first guess would be that I could call a function from parent and pass arguments, which in return calls .move_and_slide(movement) in Player.gd. But then again, Player.gd does not know about the variable movement and would throw an unknown identifier error.

nooberdev | 2018-08-06 19:02