godot
godot copied to clipboard
3D CollisionObject signals do not trigger when mouse is in "captured" mode
Godot version: 3.1.1
OS/device including version: Windows 10 Pro version 1809, Ryzen 5 2600X, GTX 660
Issue description: First off, I'm not sure if this behavior is intended. The documentation says that mouse movement and button presses should still be handled when the mouse mode is set to "captured," but CollisionObject event signals only respond to the mouse when it's in the other three modes. This includes mouse_entered(), mouse_exited(), and input_event() signals, though I only included an input_event() signal in the minimum reproduction project.
It is possible to work around this issue by ray casting from the camera, but that requires a bit more code and a tiny performance decrease.
Steps to reproduce:
- Set up a signal on a CollisionObject.
- set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
- Attempt to trigger the signal.
Minimal reproduction project: Test.zip
I think this is intended. Yes, the movement is captured, but it's about relative movement. You can get an event with how much the mouse moved, but you can't get the exact position. And without position, events that require cursor in certain area (like clicking on object, or mouse enter) won't get triggered.
I was suprised by this issue too. My expectation was, that I get InputEventMouseButton events with position in the middle of the screen also in the _input_event handler of a CollisionObject. This would get me nearer to not change code when I switch cameras between RTS like top-view mouse clicking and FPS view triggering an action in front of me.
When it is in fact intended behaviour, it needs documentation.
Same problem here in v3.2.1 and this is needed for FPS type games where the mouse is captured. The documentation says there is no need to do raycasting because we have these input events but the events don't work.
@songangel72 I once fixed that for my playground project, but didn't took the time to fully finish the PR. You could take over it if you want to https://github.com/godotengine/godot/pull/31024
+1 setting up a RayCast
because of that
I think this is intended.
Was a decision ever made on this? I was hoping that payload's pull request would have been put in to address the issue.
Still doesn't work as of 3.4.4.
Was a decision ever made on this? I was hoping that payload's pull request would have been put in to address the issue.
Feel free to look into salvaging @payload's pull request, but it didn't look like a complete working solution to me. It's worth trying nonetheless :slightly_smiling_face:
Yes please if you want @CactusPhD take the two small code changes. It was working back then but I had doubt about some code path, hence the note "Is this consistent with events which go through _unhandled_input?". All other open checkboxes are just documentation related.
I am making an FPS in Godot 4 (alpha 3 atm) where the mouse is captured and I want to use the input_event signal to know when the "mouse" (really, the middle of the screen) is over an object. This issue seems to be present and is forcing me to use a ray instead. Is there any news about it?
I am making an FPS in Godot 4 (alpha 3 atm) where the mouse is captured and I want to use the input_event signal to know when the "mouse" (really, the middle of the screen) is over an object. This issue seems to be present and is forcing me to use a ray instead. Is there any news about it?
See https://github.com/godotengine/godot/pull/31024, which needs to be salvaged to work on the latest master
branch.
Still doesn't work as of 4.1
Can confirm that this doesn't work on 4.2.1 either. The documentation concerning this issue is still very misleading.
how has this been a bug for 5 years
Nobody asked but here is my workaround code (very specific - modify it).
It emulates sending mouse events to colliders but instead of real captured mouse ray from camera it uses Raycast3D
node.
# This raycast should point from camera to player aim
@onready var raycast2 = $Head/Camera/RayCast2
var last_picked_collider_rid = null
var last_picked_collider = null
func _physics_process(delta):
raycast2.force_raycast_update()
if not raycast2.is_colliding():
if last_picked_collider:
last_picked_collider.mouse_exited.emit()
last_picked_collider = null
last_picked_collider_rid = null
return
var rid = raycast2.get_collider_rid()
var collider = raycast2.get_collider()
if rid != last_picked_collider_rid:
if last_picked_collider:
last_picked_collider.mouse_exited.emit()
collider.mouse_entered.emit()
var event = InputEventMouseMotion.new()
if Input.is_action_pressed("shoot"):
event = InputEventMouseButton.new()
event.button_mask |= MOUSE_BUTTON_MASK_LEFT
event.button_index = MOUSE_BUTTON_LEFT
event.pressed = true
collider.input_event.emit(camera, event,
raycast2.get_collision_point(),
raycast2.get_collision_normal(),
raycast2.get_collider_shape())
last_picked_collider = collider
last_picked_collider_rid = rid