Godot Version
4.4
Question
Also posted at r/godot (https://www.reddit.com/r/godot/comments/1lg1l8y/rightclick_input_not_working_when_ui_is_visible/)
Hello,
I’m currently prototyping a 3D top-down game in Godot and recently started adding a UI system. I ran into an issue when handling mouse input after displaying a UI panel.
I have a simple scene: a room with one player and two enemies.
First, here’s how the intended interaction system is designed:
Player Interaction System:
Player Actions:
mouse_left: used for movement and selecting enemies.
mouse_right: used to initiate attacks.
Left Click on the Map:
The player should move to the clicked location.
Left Click on an Enemy:
The enemy should be marked/selected.
A UI panel should appear showing:
Enemy’s name
Enemy’s level
Enemy’s current health
Left Click on Empty Space (while an enemy is marked):
The current enemy selection should be cleared.
The UI panel should be hidden.
Right Click on an Enemy:
The player should move toward the enemy.
Once within range, the battle should start.
The Problem:
After an enemy is marked (via mouse_left) and the UI panel appears, the player can still move by clicking on the map — which is correct.
However, mouse_right on another enemy does nothing.
It’s as if the mouse_right input is ignored or blocked when an enemy is already marked and the UI is visible.
If I unmark the current enemy (by mouse_left empty space, which hides the UI), then mouse_right works again as expected.
Relevant Code:
# player.gd
@onready var navigationAgent: NavigationAgent3D = $NavigationAgent
func _unhandled_input(event) -> void:
if can_move:
if event.is_action_pressed(mouse_left):
if target != null:
target = null
var result = dispathRay()
if result.has("collider"):
var col = result.collider
if col is Enemy:
if col == markedEnemy:
return
game_manager.unmark_enemy(markedEnemy)
markedEnemy = col
game_manager.mark_enemy(markedEnemy)
return
else:
if markedEnemy != null:
game_manager.unmark_enemy(markedEnemy)
markedEnemy = null
if result.has("position"):
var pos = result.position
navigationAgent.target_position = pos
if event.is_action_pressed(mouse_right):
var result = dispathRay()
if result.has("collider"):
var col = result.collider
if col is Enemy:
target = col
markedEnemy = target
game_manager.mark_enemy(target)
func dispathRay() -> Dictionary:
var camera: Camera3D = get_tree().get_first_node_in_group("Camera")
var mousePos: Vector2 = get_viewport().get_mouse_position()
var rayLength: int = 100
var from: Vector3 = camera.project_ray_origin(mousePos)
var to: Vector3 = from + camera.project_ray_normal(mousePos) * rayLength
var space: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
var rayQuery: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
rayQuery.from = from
rayQuery.to = to
return space.intersect_ray(rayQuery)
# game_manager.gd
const MARK = preload("res://assets/common/mark.tscn")
func mark_enemy(enemy: Enemy):
PlayerHud.showEnemyCard(enemy)
if enemy.get_node_or_null("Mark") != null:
return
var mark = MARK.instantiate()
enemy.add_child(mark)
func unmark_enemy(enemy: Enemy):
if enemy == null:
return
PlayerHud.hideEnemyCard()
var mark = enemy.get_node_or_null("Mark")
if mark != null:
mark.queue_free()
What I’m Looking For:
Why would mouse_right input stop working while the UI is visible, even with mouse_filter = IGNORE?
Is there a better way to structure this interaction logic to avoid UI interference?
Could this be related to how I’m managing selection or raycasting?
I’ve also tried to remove everything related to “mark”, to keep only with the show GUI part. But the problem persist.
Definitely something is consuming the input event. When the PlayerHud is active _unhandled_input isn’t called anymore.
None of my GUI nodes are set to full rect.