Parsing variables into an instantiated node to use in "func _ready()"

Godot Version

4.1.1.stable

Question

I am fairly new to Godot and have been trying to make a centipede clone, but I keep running into an issue. To get it to work (with my implementation) I need to create a sibling node that is the same as the one that made it, but with a different value in a length variable. I have seemingly tried everything but signals so far, and haven’t found a way to parse the information to the node when I instantiate it. My current issue is that when I try to call a custom “func instantiate” it refuses to recognize it, despite the function itself working and being able to set properties such as position just fine. Current attempt is below, and it all occurs in this one script as I am instantiating the same node that creates the instance.

Also, I am aware of the small inefficiencies, I just want to get this working.

extends Area2D

@export var length : int = 12

@onready var segment_scene = preload("res://project_files/centipede/scenes/centipede_segment.tscn")


func _ready():
	var segment = segment_scene.instantiate()
	get_parent().add_child(segment)
	segment.instantiate(length, position.x, position.y)
	#when I run this line, I get the error:
	#Invalid call. Nonexistent function 'instantiate' in base 'Area2D'.


func _process(delta):
	pass


func instantiate(old_length, position_x, position_y):
	length = old_length - 1
	position.x = position_x + 32
	position.y = position_y

WRONG ANSWER
You instantiate segment_scene in a var named segment.
Then you try to instantiate segment again. But segment is already an instance.

Instead of the second instantiate, you can juste change the properties values

segment.length = length
segment.position = Vector2(position.x, position.y)

Edit : oops! I didn’t see the instantiate function.

No worries, but I was also wondering about “segment.length”. I did try doing exactly that and not using the custom function, but I then get the error that “length not found in base ‘Area2D’”. I get why it says that it isn’t in the base Area2D, but I don’t see why it looks at the Area2D and ignores the export variable.

Weird. I juste tested it and it seems to happen when it is the same scene.
the solution might be to duplicate the current segment:
replace

 	var segment = segment_scene.instantiate()

with

	var segment = self.duplicate()

Do you have any other errors in the bottom dock when you run your game?

Do you have custom _init() function by any chance?

From the looks of it what happens is that during instantiation Godot encounters a problem with the script attached to the scene and just skips it. So the resulting scene is a bare base Area2D which indeed doesn’t have instantiate() function or length property.

I don’t have an _init function, but I am getting some path errors so I’ll check those real quick

I am now very confused, as it could definitely have something to do with it not being able to find the scene in the file tree, but the path is correct so I’m not sure why it says it can’t find the resource. Specific error message is “E 0:00:00:0655 _parse_ext_resource: res://project_files/centipede/scenes/centipede_segment.tscn:234 - Parse Error: [ext_resource] referenced non-existent resource at: res://project_files/centipede/scripts/centipede_segment.gd”

I think I see the problem perhaps, it thinks the script is in a different folder than it is.

Then you need to fix these errors first.

If Godot can properly load the script file, it should just work (except for a potential infinite loop you created).

I started stripping things down, and I think that maybe Godot doesn’t like that I am technically (for less than a frame) trying to instantiate a scene inside itself. If that is the problem (as the only errors seem to be from that), how could I avoid that? Create the instance as a child of parent?

There is a plethora of pitfalls in this setup.

A scene loading itself with preload.

A scene adding a child to the parent in _ready() function, when parent is not ready yet.

A scene adding a scene, that adds a scene, that adds a scene in an infinite loop with no exit condition.

I am aware of the many issues this is causing, so I guess it’s time to just restart fresh knowing that recursion, creating oneself and of course the infinite loop (that I was going to fix but is still note worthy) are not typically very good things. You could probably make a game about those concepts, though.

I think that it is bad practice to create nodes from siblings. The parent node should be the one creating children.

Also, by using the Node.duplicate() function, you can avoid preloading the scene.

You could’ve just done it in the parent instead, with one simple loop.

func create_segments(start_length, start_position):
	var i = 0
	for length in range(start_length, 0, -1):
		i += 1
		var segment = segment_scene.instantiate()
		add_child(segment)
		segment.length = length
		segment.position.x = start_position.x + 32*i
		segment.position.y = start_position.y

Obviously untested, but you get the idea

1 Like

Yeah, I think the lesson is follow best practices, especially if you don’t know what you are doing (me)

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