Mouse entered/exited unreliable?

Hi!

I have a problem with a node that looks like this:

Area 2D (parent)
----- Sprite 2D (child)
----- CollisionShape 2D (child)

This is meant for a GUI control. I need to know whether the mouse is hovering over it, so I have set up the mouse_entered and mouse_exited signals for the collision shape child node. Each one has a simple “print” command to check whether the mouse is hovering over it.

The issue is that these signals trigger fine sometimes but not always. For instance, if the mouse enters and exits the collision area too fast, the signals won’t pick it up.

Is there any better/more reliable way to do this?

Thanks!

If you move the mouse so fast, that on one frame it is left of the CollisionShape and on the next frame it is right of the CollisionShape, then Godot doesn’t register it being in the CollisionShape in-between. So this use-case is currently not supported by Godot.

If you need to cover these situations, then you will need to implement functionality that compares the mouse-position between two subsequent frames and act accordingly.

It is possible, that Input.use_accumulated_input = false would help a little bit in your case.

Thanks very much for your quick reply.

I will look into that, but it does not seem to be the real problem (not the full problem anyway). Exiting/entering too fast can be an issue sometimes, but not always. Sometimes it does not trigger even if the mouse moves slowly into the collision shape. I just provided that example to illustrate what happens, maybe I misled you.

I find this puzzling.

In these cases, the mouse_enter/exited signals should trigger, except when other nodes interfere with that:

  • For example Control nodes are always handled first, before CollisionShapes.
  • Embedded windows can also interfere with that logic in certain situations

Without more details about your implementation, it is difficult to guess, if this is a bug or not.

The mouse_entered and mouse_exited signals have always been very reliable for me. However, as another option for you, rather than using signals, you could just check the position of the mouse something like this:


@onready var my_sprite = $Sprite2D


func _process(_delta):
	if is_mouse_over_sprite(my_sprite):
		print("Mouse is over the sprite")


func is_mouse_over_sprite(sprite):
	var mouse_pos = get_global_mouse_position()
	var sprite_rect = Rect2(my_sprite.global_position, my_sprite.texture.get_size() * my_sprite.scale)
	return sprite_rect.has_point(mouse_pos)


I tested this and it works extremely well. Hope that helps.

Nevermind. I found the issue. There was a misplaced control gui over the collision areas that was messing everything up. It was invisible, so I couldn’t tell until the idea somehow clicked in my mind.

Thanks pauldrewett and Sauermann for your help anyway!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.