Nonexistent Function Call in base 'Nil'

Godot Version

Godot 4.3 Stable

Question

This is severely confusing the hell out of me. I’m a fluent developer of Python, but not with Godot Script yet. I’ve developed for over 5 years in Python, but was limited to what I wanted to achieve, so have been trying to port my game in Python, over to Godot. I followed a tutorial, and have a working game, and tried to model my class/script based on other code that works, and my code does not work.

I’m getting an error of:

" Invalid call. Nonexistent function ‘generate_item’ in base ‘Nil’ "

Based on this error, I’m assuming the base class is not being initialized/instantiated and thus why it cannot find the function. However, I’m not sure what I’m doing wrong.

So I’ve tested the code within the main script first, and the code works properly, but I don’t want to bloat the main script with a ton of code, so I wanted to send the data to a large code block in another script file, to keep things clean and orderly.

In the main script I have this up at the top:

@onready var item_gen: GeneratorOfItems

The script it is in, is called generator_items.gd

This is the code in that script:

class_name GeneratorOfItems
extends Node

var _rng := RandomNumberGenerator.new()

func _ready() → void:
_rng.randomize()
print(“it exists”)

func generate_item(new_entity) → Entity:
var weapon_names: Array[String] = [‘Blade’, ‘Shortsword’, ‘Scimatar’, ‘Rapier’]
var icons: Array[Vector2i] = [Vector2i(512,112), Vector2i(528,112), Vector2i(544,112), Vector2i(560,112), Vector2i(576,112)]
var chosen_name: String = weapon_names[_rng.randi_range(0, len(weapon_names) - 1)]
var chosen_icon: Vector2i = icons[_rng.randi_range(0, len(icons) - 1)]

new_entity.texture.region = Rect2(chosen_icon, Vector2i(16,16))
new_entity.entity_name = chosen_name
print("Success")
return new_entity

Called every frame. ‘delta’ is the elapsed time since the previous frame.

func _process(delta: float) → void:
pass


Now it should be noted the _ready function doesn’t get called, as I never see “it exists” in the log and then it errors out when it tries to call generate_item.

I’ve tried every permutation I can think of to try to fix this issue, but I don’t understand Godot Script enough to figure it out on my own. I tried googling the issue, and none of the answers I found address my question.

try

@onready var item_gen: GeneratorOfItems = [path to generator_items.gd]

Typed this:

@onready var item_gen: GeneratorOfItems = [“res://source/Generators/generator_items.gd”]

Got this error:

Cannot assign a value of type Array to variable “item_gen” with specified type GeneratorOfItems.

sorry for the confusion

@onready var item_gen: GeneratorOfItems = preload("res://source/Generators/generator_items.gd").new()
1 Like

That worked. Surprisingly. Why is it that I have to use the .new() here, but in other places where a class is loaded into a variable, or calling a non-static function from elsewhere, it isn’t needed.

I appreciate the help… now to know why new() is needed…

I think in Godot script needs to be attached to a node
so you want item_gen to be an object not just a script


This way you basically access the object func
Also, there is some problem with [func _ready] not being loaded in some other cases so load it as an object to ensure it loads, the subject is a bit broad so I might be wrong.

That does make some sense.

Its just that there are a number of scripts not attached to a scene, that are used as member classes.

ie classname FighterComponent

fighter_component: FighterComponent

entity.fighter_component.take_damage(3)

and that works without requiring the .new().

Regardless, at least now the code works and can continue.

Thanks again!

1 Like

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