Invalid call. Nonexistent function 'init' in base 'CharacterBody2D'

Godot Version

4.1.2

Question

I’m trying to create some scripts to learn OOP in Godot and I keep getting this error “Invalid call. Nonexistent function ‘init’ in base ‘CharacterBody2D’.”

Here is my main parent class:

extends CharacterBody2D
class_name Char

var _name: String
var _hp: int
var _age: int
var isDead: bool

func _init(string_name: String, hp: int, age: int):
	set_charname(string_name)
	set_hp(hp)
	set_age(age)

func get_charname():
	return _name
func set_charname(string_name: String):
	_name = string_name
	
func get_hp():
	return _hp
func set_hp(hp: int):
	if hp <= 0:
		isDead = true
		hp = 0
	else:
		isDead = false
		_hp = hp
	
func get_age():
	return _age
func set_age(age: int):
	assert(!(age < 18), "Only 18+ age allowed")
	_age = age

Here is my NPC class, that inherits from Char:

extends Char
class_name NPC

var _friendly: bool
var _faction: String

func init(npc_name: String, hp: int, age: int, friendly: bool, faction: String = ""):
	_init(npc_name, hp, age, friendly, faction)

func _init(npc_name: String, hp: int, age: int, friendly: bool, faction: String = ""):
	super(npc_name, hp, age)
	set_friendly(friendly)
	set_faction(faction)

func _ready():
	print(get_faction())
	
func get_friendly():
	return _friendly
func set_friendly(friendly: bool):
	_friendly = friendly

func get_faction():
	return _faction
func set_faction(faction: String):
	_faction = faction

And then I try to call it inside a Scene:

extends Node2D

# Called when the node enters the scene tree for the first time.
func _ready():
	init_npc()
	#pass

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass
	
func init_npc():
	#Roberto
	var roberto = load("res://Scenes/npc.tscn").instantiate()
	roberto.position = Vector2(400, 200)
	roberto.init("Roberto", 200, 20, true, "Test")
    add_child(roberto)

Then it throws that error “Invalid call. Nonexistent function ‘init’ in base ‘CharacterBody2D’.” because of this line:

roberto.init("Roberto", 200, 20, true, "Test")

But as you can se in the NPC.gd, init function definitively exists

I don’t understand what is wrong with this code, the parent node from
“res://Scenes/npc.tscn” is from type NPC, so not really sure what’s happening. If anyone can shed a light I would be very thankful.

The root node would need that NPC script on it, could you show your scene tree? overriding _init with extra parameters makes the type much more difficult to work with. I would be surprised if you could instantiate it at all.

1 Like

The documentation says, that if _init is defined with required parameters, the Object with script may only be created directly. If any other means (such as PackedScene.instantiate or Node.duplicate) are used, the script’s initialization will fail.

Your NPC object doesn’t have a script, because scene instantiation needs to call _init() without parameters.

2 Likes

Ooooh, yep, that was it. So, to make what I’m doing work I made the paremeters optional on my _init, this way it still can instatiate without parameters but I still call the constructor to run when I call my “init” function, this way defining the values I wanted for the object.

Do you think this is a bad way around it?

Wait, I’m overwriting the _init function? Isn’t it the constructor for the class?

Or are you talking about the “init” function that I created? The only reason I created it is because I couldn’t call “_init”.

both NPC and Char have _init overrides. It’s the func _init(... usually a blue arrow appears in the gutter by the line numbers.

1 Like

Using default values for the parameters is a valid solution. I can’t say if it’s a good or a bad solution without properly understanding your intention, but the important thing is that it works.

The way constructors work in GDScript is that you override _init or _static_init functions.

2 Likes