Godot calls function but also throws "Can't call non-static function" error

Godot Version

4.2.2

Question

Hi, I am trying to get my head around classes in Godot and wrote some code which works… but Godot is still throwing the error “Can’t call non-static function ‘reset_button’ in script”. My question would be: Is the error a false interpretation by Godot or am I understanding something wrong?

I have two scripts:

  1. PlayerSkill (class_name), which is a simple scene with a button and a cooldown timer and a function “cooldown_reset”.
  2. CombatDebug, an autoloaded debug script which holds an array of PlayerSkills and resets all of them when a button is pressed.
class_name PlayerSkill
extends Node

@onready var player_skill_button = $"."

func _ready():	
	CombatDebug.cooldown_actions.append(self)

func reset_button():
	player_skill_button.disabled = false
	texture_progress_bar.value = 0

Snippet of the autoloaded debug script

var cooldown_actions = [PlayerSkill]
func cooldown_reset():
	# for all PlayerSkills -> reset
	for action in cooldown_actions:
		action.reset_button()
	pass

Now this works like a charm, but the error irritates me and I dont want to continue bad practises or error prone code. Thanks in advance :slight_smile:

This is an array of PlayerSkill (the class/script itself) and not an instance of PlayerSkill (i.e. something that exists in the SceneTree). reset_button is an instance method, not a static method, hence the error.

I think the intent here is to have instantiated a node based on PlayerSkill and call its reset_button method.

1 Like

Yes, you can only access static functions without initializing,hence the error. Static functions and variables are able to be accessed without any initialization. For more information, check the gdscript reference page(
Static variables
)

So would the “correct” way forward be to remove the specification of the array and just pass the node? My idea was to keep the debug code readable and to clearly show, that this a method from the PlayerSkill class.

I understand, but I can access it… that’s what’s confusing about it. It works fine. Everything does what it should, but it throws the error. Static functions wouldnt work here because I want to reset only the specific instantiated button.

You should initialize with an empty array. I think that one PlayerSkill you have by default-which might be referring to a variable, but probably isn’t-might be causing the error. If you want, you can initialize and put default properties in it, so that it acts as a default player skill, or one you get at the beginning of the game.

1 Like
# array with one element of a type
var cooldown_actions = [PlayerSkill]

If you wanted a typed array you need to put a colon after the variable name

# array of PlayerSkill elements
var cooldown_actions: Array[PlayerSkill] = []

Rather than adding your player skills to the debug directly, try using groups

func cooldown_reset():
	for action in get_tree().get_nodes_in_group("player_skills"):
		action.reset_button()

On an unrelated note this line gets the current node, not a button. It’s the same as using self or just disabled = false. How is texture_progress_bar defined?

@onready var player_skill_button = $"."
1 Like

Thanks, changing the declaration of the array removed the error. Still wondering why the code worked before but it’s probably due to GDScripts dynamic nature.

player_skill_button and self are not the same though, the button is a reference to the instance (object) while self is a reference to the script. I use the button reference to change its texture after initializing it, this doesn’t work with self. Just writing disabled = false doesn’t let me compile and the editor shows an error.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.