+5 votes

I've add a CanvasLayer and added a Sprite, Area2D and CollisionShape2D as child nodes.

I cannot get any of the children in the CanvasLayer to receive mouse input events. Only the root node is receiving input events.

Why is this?

in Engine by (17 points)
edited by

does your area2d have the "pickable" property enabled ?

I have the same issue as him and in my case I have "pickable" property enabled, in fact, if I move the Sprite>>Area2D >>Collision block outside the CanvasLayer it works perfect. But I'm not able to make it works inside the CanvasLayer

4 Answers

–2 votes

I have the same problem. Does anybody have any clue?
I tried to explore the c++ sources but didnt succeed

by (23 points)
+1 vote

I don't think this is the best solution but this is the workaround I made to detect clicks on a joystick node that is child of a CanvasLayer. I have a structure like this:

  • mainNode

    • World

      • Player

        • Camera2D
      • Monsters

  • UI (this is the CanvasLayer)

    • health

    • menu

    • joystick (I want to manage click here)

      • joystickBtn

What I did was:

  • Add a script on the "joystick" node
  • Manually detect clicks by position
  • If click position belongs to the area I want, I call a function from the Player node

Sample code for joystick node (Godot 3):

extends Node2D
onready var joystickBtn = get_node("joystickBtn")
var btnPos = Vector2(0,0)
var btnSize = Vector2(0,0)
var btnRect2 = Rect2(Vector2(0,0), Vector2(0, 0))

func _ready():
    set_process_input(true)

    # Generate a Rect2 on the place we want to manage click
    # For this example the are will be obtained from a button
    btnPos = joystickBtn.get_global_position()
    btnSize = joystickBtn.get_size()
    btnRect2 = Rect2(btnPos, btnSize)     

func _input(event):
    var player = get_node("/root/mainNode/World/Player")
    if event is InputEventMouseButton: # If event is mouse click
        # Get click position
        var clickPos = Vector2(event.position.x, event.position.y)

        # If event is pressed and position belongs to btnRect2
        if event.pressed and btnRect2.has_point(clickPos):
            player.my_custom_function("arg1", "arg2")
by (82 points)
0 votes

For this I used ColorRect node as background and changed the atribute in "Mouse" - "Filter" from "Stop" to "Ignore". And my input events start to work like a charm.

I think its usable for every node in Control family as they have Mouse/filter parameter

by (14 points)

The problem in this case is that the CanvasLayer where the object is located blocks the input_event. Your solution works when it is a Control node that blocks the object.

0 votes

The only solution I have found is to have all objects that make use of input events in nodes that inherit from CanvasItem like Node2D or Control, but never inside a CanvasLayer node, which inherits from Node and blocks all input events.

by (211 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.