`I cannot get anything to happen when clicking on the collision 2d when running the game using input_event.connect(_on_input_event) I have pickable on, the node2d has collisionshape2d attached to it as well with both layers on 1. the input events reciever message is _on_input_event yet nothing in the _on_input_event() runs at all not even the print statement that says “On input ran”. here is the code for this scene:
extends Area2D
@export var pickup_radius : float = 50.0 # Adjust in Inspector!
var player: Node2D
var distance: float
func _ready():
# Connect mouse input signal to detect clicks
input_event.connect(_on_input_event)
func _on_input_event(viewport, event, shape_idx):
print(“On input ran”)
# Check if it’s a left mouse click
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
player = ItemDatabase.player # Get player from autoload
if player:
distance = global_position.distance_to(player.global_position)
print("Floor item clicked! Distance to player: ", distance)
if distance <= pickup_radius:
print("Player is close enough to pick up!")
# Add your pickup logic here (e.g., player.pickup_item(self))
else:
assert(false, "Error: Player not found in ItemDatabase!")
I am very new so take my advice with a massive grain of salt. I understand this likely less than you do. Right off the bat, is there a reason your character isn’t a characterbody2D?
So is this an area within your gamespace, that you can click on and get items from? Like clicking agroup of corn crops and picking up corn from them if you’re close enought?
Its okay! CharacterBody2D is for physics-based characters that need collisions/movement. Its better to use area2d in this scenario because it It doesn’t need physics collisions, It specializes in detection zones and input events and its perfect for pickups, interaction zones, etc. Also your idea of the scene is somewhat correct but the “area” in area 2d is only actually the clickable area around an item. This entire scene isn’t the area that inhabits the items(if that’s what your asking) rather it represents a single item that can be clicked and interacted with. My issue is that its not doing anything with my clicks.
Yes this is beyond me. I’m sorry I hope you get help. To me, the only thing I could think is if the player wasn’t really anything and was being set up as more of an empty folder in your script, but I see now you have a player.gd script set up so I am stumped
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
break this into smaller parts, you are doing too many checks at the same time and that leads to bugs.
if event is InputEventMouseButton:
if event.is_pressed():
if event.button_index == MOUSE_BUTTON_LEFT:
#do stuff
also you are doing pressed which is never going to work. the correct is is_pressed()
else:
assert(false, "Error: Player not found in ItemDatabase!")
don’t use assert. specially not in a player script, specially not in an item script.
and it’s not needed here, all paths should work or do nothing.
and checking if the player exists should be done somewhere else, not in an item.
it says there that the signal is already connected.
disconnect it. you are connecting it from code.
go to the signal, right click and disconnect.
edit:
I missed this. don’t proxy your reference, use the one from the autoload.
you can create a function in autoload to get the player distance directly and check if player exists at the same time.
if you need a pickup radius per area instead of a global one, then return distance and compare in input_event:
func get_player_distance(area : Node2D) -> float:
if player:
return area.global_position.distance_to(player.global_position)
else:
return 0#or a big number so it doesn't pickup
Hey thanks for responding. I did my best to implement everything you advised but the issue is still just that nothing in the _on_input_event() is executing at all. I can put a print statement in it without conditions and it will never print. I also disconnected the signal in the editor. Here is the updated code:
extends Area2D
@export var pickup_radius: float = 50.0 # Configurable per item in Inspector
func _ready() → void:
# Connect mouse input signal
input_event.connect(_on_input_event)
func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) → void:
# Early returns for cleaner input handling
if not event is InputEventMouseButton:
return
if not event.is_pressed():
return
if event.button_index != MOUSE_BUTTON_LEFT:
return
# Use the autoload's distance check function
if ItemDatabase.is_player_in_range(global_position, pickup_radius):
print("Player picked up item!")
# Add pickup logic here:
queue_free()
else:
print("Player too far away (Distance: ",
global_position.distance_to(ItemDatabase.player.global_position), ")")
Have you checked, if the Root Window has physics Object Picking set to on?
Project → Project Settings… → Physics → Common → Enable Object Picking (You might need to activate “Advances Settings”)
Have you checked, where the CollisionShape2D is located? Perhaps it is not at the same location as the Sprite2D.
Have you checked the size of the CollisionShape2D? Perhaps it is too small.
Have you checked, if any Control node intercepts the InputEvent?
You found the issue thank you! It was that last one, I had a debug menu that only had text covering a small part of the top left, but the entire box covered the entire screen (even if invisible) so it works now.