4

After testing out a few other engines I've settled into Godot for my game development learning process and have really appreciated the conciseness of GDScript, the node/inheritance structure, and the way observer events are covered by signals. I've been building knowledge through various tutorials and by reading through the documentation.

Somehow I'm struggling to solve the very fundamental task of detecting a mouseclick on a sprite. (Well, on a sprite's parent node, either a Node2D or an Area2D.)

My process has been this:

  1. Create an Area2D node (called logo) with a Sprite child and a CollisionShape2D child
  2. Assign a texture to the Sprite node, and change the x and y extent values of the CollisionShape2D node to match the size of the Sprite's texture
  3. Connect the _on_logo_input_event(viewport, event, shape_idx) signal to the Area2D node's script (called logo.gd)
  4. Use the following code:
func _on_logo_input_event(viewport, event, shape_idx):
    if (event is InputEventMouseButton && event.pressed):
        print("Logo clicked")

When I run the game I get nothing in the output after clicking, and see these errors:

The argument 'viewport' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_viewport'

The argument 'shape_idx' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_shape_idx'

I don't know how to address the parameters in this signal's function - My Area2D node is set to Pickable, and the logo Area2D node is a direct child to the game_window Node2D in the main scene. I can't figure out what is going wrong here, whether it's some project setting I need to change or an inspector attribute I need to set. Is there a better way to feed an input signal for a mouse click into a script?

I don't want to clutter stackoverflow with such a simple question but I've tried to do my due diligence and haven't been able to find this error message on any forums. I'd appreciate any help, thanks.

Sean Simon
  • 43
  • 1
  • 5

2 Answers2

5

If the CollisionLayer of your Area2D is not empty, and input_pickable is on, then it is capable to get input. Either by connecting the input_event signal or by overriding _input_event.

If that is not working, the likely cause is that there is some Control/UI element that is stopping mouse events. They have a property called mouse_filter, which is set to Stop by default. You will need to find which Control is intercepting the input, and set its mouse_filter to Ignore.


By the way, these:

The argument 'viewport' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_viewport'

The argument 'shape_idx' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_shape_idx'

These are warnings. They are not the source of the problem. They tell what they say on the tin: you have some parameter that you are not using, and you can prefix its name with an underscore as a way to suppress the warning.

Theraot
  • 31,890
  • 5
  • 57
  • 86
  • Thank you for taking the time to share these considerations - I'll jump back into the project later and look for any control or UI elements that might be intercepting mouse events. One question: you say the collision layer of the Area2D node shouldn't be empty — is selecting a rectangle shape for the CollisionBody2D child node and setting its extents in the inspector all that's needed for it to not be empty? I'm glad to know the debugger warnings are not indications of a larger problem - I didn't know if the viewport was incorrectly set up or something. – Sean Simon Jul 15 '21 at 20:00
  • @SeanSimon I mean that the `collision_layer` of the `Area2D` should not be 0. It is 1 by default. if you haven't touched it, it is fine. This limitation is going away in future versions, but still holds in the current stable. The property `input_pickable` is also on by default. So you only need to give it a collision shape. By the way, you look first for a `Control` that covers the whole screen. Perhaps some container, or if you have a control for background, something like that. See also https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html#how-does-it-work – Theraot Jul 15 '21 at 20:12
  • Thank you! I've solved this after some trial and error inspired by your answer - I had a TextureRect as a background image, and its mouse filter was set to pass. At first I thought that was correct, but it seems like "pass" doesn't mean that clicks pass through it, and what I really needed was "ignore". I thought setting it to a lower Z-index than the other elements meant that other nodes would 'receive' the click before the click interacted with the TextureRect background, but I guess not! – Sean Simon Jul 15 '21 at 23:23
1

I would also recommend checking out this video: https://www.youtube.com/watch?v=iSpWZzL2i1o

The main modification that he makes from what you have done is make a separate click event in Project > Project Settings > Input Map that maps to a left click. He can then reference that in the _on_Area2D_input_event.

extends Node2D

var selected = false

func _ready():
    pass

func _on_Area2D_input_event(viewport, event, shape_idx):
    if Input.is_action_just_pressed("click"):
        selected = true
        
func _physics_process(delta):
    if selected:
        global_position = lerp(global_position, get_global_mouse_position(), 25 * delta)

func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT and not event.pressed:
            selected = false




Michael Eliot
  • 831
  • 8
  • 18