Clicks fall through the enemy onto the map

Godot Version

4.4.1

Question

When tapping the enemy it's also taping on the map

Hello again, I need some help with the enemy. When tapping on it, it also shows I tapped on the map.
Here is my enemy input code:

func _on_enemy_body_input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		player.attacking = !player.attacking
		if player.attacking == true:
			player.animation_tree["parameters/conditions/attacking"] = true
			player.id_path = map.find_path(player.global_position, global_position)
			target_enemy = load("res://Enemies/Target_enemy.tscn").instantiate()
			add_child(target_enemy)
		else:
			player.animation_tree["parameters/conditions/attacking"] = false
			remove_child(target_enemy)

As explained in the documentation Using InputEvent — Godot Engine (stable) documentation in English the physics picking event (what you are using for the enemy) is the last step in the input event chain so whatever step you are using for checking if the map has been clicked will probably come first.

The easiest fix I can think of is to use a Control node in your enemy to intercept the mouse events by connecting its Control.gui_input signal to the function and Viewport.set_input_as_handled() the event when needed

I don’t know if I did it correctly but now I can’t tap on the enemy.

func _on_enemy_body_input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		_on_control_gui_input(event, viewport)
		player.attacking = !player.attacking
		if player.attacking == true:
			player.animation_tree["parameters/conditions/attacking"] = true
			player.id_path = map.find_path(player.global_position, global_position)
			target_enemy = load("res://Enemies/Target_enemy.tscn").instantiate()
			add_child(target_enemy)
		else:
			player.animation_tree["parameters/conditions/attacking"] = false
			remove_child(target_enemy)

func _on_control_gui_input(event: InputEventMouseButton, viewport: Viewport) -> void:
	if event:
		viewport.set_input_as_handled()

Maybe I put Control node in the wrong place?

Sorry, I meant to move the logic of the _on_enemy_body* function into the signal’s callback.

I don’t know… Maybe something else is happening, like entire different problem but it’s still not working.

func _on_control_gui_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		get_viewport().set_input_as_handled()
		print("Tapped enemy!")
		player.attacking = !player.attacking
		if player.attacking:
			player.animation_tree["parameters/conditions/attacking"] = true
			player.id_path = map.find_path(player.global_position, global_position)
			target_enemy = load("res://Enemies/Target_enemy.tscn").instantiate()
			add_child(target_enemy)
		else:
			player.animation_tree["parameters/conditions/attacking"] = false
			if is_instance_valid(target_enemy):
				remove_child(target_enemy)

Green border is supposed to be only for map

How are you dealing with the tilemap input event? Are you using _input() or _unhandled_input(). If you are using _input() then change it to _unhandled_input() so it happens after _gui_input() as the documentation I linked above explains.

This work fine:

extends Node


@onready var sprite_2d: Sprite2D = $CharacterBody2D/Sprite2D
@onready var tile_map_layer: TileMapLayer = $TileMapLayer


func _ready() -> void:
	$CharacterBody2D/Control.gui_input.connect(func(event):
		if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
			sprite_2d.modulate = Color.RED
			tile_map_layer.modulate = Color.WHITE
			get_viewport().set_input_as_handled()
	)

func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		sprite_2d.modulate = Color.WHITE
		tile_map_layer.modulate = Color.RED

1 Like