.connect() Object to Callable issues

Godot Version

4.1.1

Question

I was attempting to connect an Area2D to a _on_body_entered and exited function but it throws an error.

Code:

extends Area2D

var rotating
var pickcollision
@onready var limb = $Beardy/Area2D/Pickaxe

func _ready():
	pickcollision = $Beardy/Area2D
	
	# Load the scene containing the TileMap
	var scene = load("res://Scenes/Themine.tscn")
	
	# Instance the scene to access its nodes
	var scene_instance = scene.instance()
	
	# Find the TileMap node within the scene
	var tilemap = find_tilemap_node(scene_instance)
	
	pickcollision.connect("tilemap_entered", self, "_on_tilemap_entered")
	# Connect the body_exited signal to the _on_body_exited method
	pickcollision.connect("tilemap_exited", self, "_on_tilemap_exited")

func find_tilemap_node(node):
	# Recursive function to find the TileMap node within the scene
	if node is TileMap:
		return node

func _on_body_entered(tilemap):
	# Called when the CollisionShape2D enters another physics body
	print("Collision entered with", tilemap.name)
	rotating = false
	pickcollision.set_disabled(false)
	limb.visible = true

func _on_body_exited(tilemap):
	# Called when the CollisionShape2D exits another physics body
	print("Collision exited with", tilemap.name)
	rotating = true
	pickcollision.set_disabled(false)
	limb.visible = true;

The error it throws:

Invalid type in function 'connect' in base 'Area2D'. Cannot convert argument 2 from Object to Callable.

I’ve looked at the docs online but can’t understand them yet lol. Thanks!

Change

    pickcollision.connect("tilemap_entered", self, "_on_tilemap_entered")
    pickcollision.connect("tilemap_exited", self, "_on_tilemap_exited")

into

    pickcollision.connect("tilemap_entered", _on_tilemap_entered)
    pickcollision.connect("tilemap_exited", _on_tilemap_exited)

The former is how it worked in Godot 3, the latter is how you connect a signal in Godot 4 now.


The error message tells you, you’re using a function (in this case connect) that expects a certain type (Callable) as its second argument, but what you gave it (self, of type Object) cannot be converted to it, thus is considered invalid. In other cases (e.g. when passing an int to a function that expects a float) that conversion would be possible and then carried out automatically by the Engine.

1 Like

Thanks, @njamster, this worked. I attempted to connect this to a different script I had, though, and now it gives me a new error.

Attempt to call function 'connect' in base 'null instance' on a null instance.

I assume this means that something isn’t instantiated yet?

Correct. You’re calling connect on a (yet?) non-existing object.

But as shown here, I’ve already instantiated pickcollision two lines above these calls.

func _ready():
	pickcollision = $Beardy/Area2D
	
	pickcollision.connect("body_entered", _on_body_entered)
	pickcollision.connect("body_exited", _on_body_exited)

What else could be the culprit?

Most likely the used node path is wrong, so either the scene doesn’t have a child node that is named “Beardy” or that node doesn’t have a child node called “Area2D”.

What gets printed if you print(pickcollision) after the first line in _ready?

Beardy is a child of the Area 2D that I have the script attached to. Would that be an issue?

If the script is attached to the Area2D itself, then you’d do:

func _ready():	
	self.connect("body_entered", _on_body_entered)
	self.connect("body_exited", _on_body_exited)

The special self keyword is used to represent the instance a script is attached to. It’s technically optional here, since Godot will assume all functions are called on that instance unless explicitly stated otherwise (by specifying another node, like in your code), but I like to include it for clarity anyway. :slight_smile:

Yeah that works, now it’s just more issues in the script that references it. Thanks!

Thank you so much man, for sollution providing. It helped me too!