I'm trying to create a clickable sprite. Using the answer from https://godotengine.org/qa/50469/implementing-clickable-sprites , I've created a scene with an Area2D, a CollisionShape2D, and an AnimatedSprite. This includes:

Area2D Campfire

  • CollisionShape2D
  • AnimatedSprite

In Campfire.gd:

signal campfire_clicked

func _input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton \
	and event.button_index == BUTTON_LEFT \
	and event.is_pressed():
		emit_signal("campfire_clicked")

func _on_Campfire_input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton \
	and event.button_index == BUTTON_LEFT \
	and event.is_pressed():
		emit_signal("campfire_clicked")

In Camp:

CampDisplay

  • ColorRect background
  • Campfire scene instance

Event campfire_clicked() is connected to _on_CampDisplay_campfire_clicked(), which will just print out a message that the campfire was clicked.

When I pull up the camp screen, I can see the campfire, but clicking on it doesn't produce a campfire_clicked event.

The approach I'm using to change to this 2D scene is a copy of one that I was able to use successfully in another context. A button added to the scene generates on-click events correctly, but the Area2D doesn't.

What have I missed?

  • My understanding is that only a Control node (which includes a descendant of a Control node) can detect an input event. A Button is a Control; an Area2D is not.

    All user interface nodes inherit from Control.
    https://docs.godotengine.org/en/stable/classes/class_control.html

    This isn't as restrictive as it sounds. You could have a Panel that covers a large portion of the viewport. The Panel (a Control) would detect input events, and the Panel's script could determine the location of the click, which could be inside the bounds of a non-Control node such as an Area2D.

My understanding is that only a Control node (which includes a descendant of a Control node) can detect an input event. A Button is a Control; an Area2D is not.

All user interface nodes inherit from Control.
https://docs.godotengine.org/en/stable/classes/class_control.html

This isn't as restrictive as it sounds. You could have a Panel that covers a large portion of the viewport. The Panel (a Control) would detect input events, and the Panel's script could determine the location of the click, which could be inside the bounds of a non-Control node such as an Area2D.

    DaveTheCoder Thanks for your quick response!

    How should I set up an animated hotspot on a 2D screen? It looks like Container might work, but I'm open to taking a different route entirely. The answer I'd found and tried to implement has evidently sent me down the wrong path.

    Update: it looks like I probably want TextureRect. I'll try that, but I'll keep an eye out for any further responses in the meantime.

    DaveTheCoder

    I tried the following:

    Campfire2 (panel)

    • FireSprite (AnimatedSprite)

    In Campfire2.gd:

    signal debug_campfire2_clicked
    
    ...
    
    func _input_event(viewport, event, shape_idx):
    	if event is InputEventMouseButton:
    		if event.button_index == BUTTON_LEFT:
    			if event.is_pressed():
    				emit_signal("debug_campfire2_clicked")
    			else:
    				print("Event "+str(event)+", button index "+str(event.button_index))
    		else:
    			print("Event "+str(event)+", button index "+str(event.button_index))
    	else:
    		print("Event "+str(event))
    
    func _unhandled_input(event):
    	if event is InputEventMouseButton:
    		if event.button_index == BUTTON_LEFT:
    			if event.is_pressed():
    				emit_signal("debug_campfire2_clicked")
    			else:
    				print("Event "+str(event)+", button index "+str(event.button_index))
    		else:
    			print("Event "+str(event)+", button index "+str(event.button_index))
    	else:
    		print("Event "+str(event))

    _unhandled_input() for Campfire2 is getting Mouse Motion and Event Key events, so I think things are getting closer; but it's not getting any InputEventMouseButton events when I click on it. Mouse Filter is the default value, Stop. Is that right?

    A useful debugging aid in the bottom dock is:
    Debugger >> Misc >> Clicked Control

      DaveTheCoder This was being clicked on correctly. It looks like I needed to connect to the signal _on_Campfire2_gui_input(), instead of using _unhandled_input() -- the signal was being handled and ignored. I'll post again if I have any further problems, but I think this is resolved... Thanks for your help!

      Update: Yes, this solves the problem! Thank you VERY much!!!