godot icon indicating copy to clipboard operation
godot copied to clipboard

3D CollisionObject signals do not trigger when mouse is in "captured" mode

Open The-Foilist opened this issue 5 years ago • 14 comments

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:

  1. Set up a signal on a CollisionObject.
  2. set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
  3. Attempt to trigger the signal.

Minimal reproduction project: Test.zip

The-Foilist avatar Jun 12 '19 19:06 The-Foilist

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.

KoBeWi avatar Jun 13 '19 11:06 KoBeWi

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.

payload avatar Jul 21 '19 19:07 payload

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 avatar Mar 11 '20 22:03 songangel72

@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

payload avatar Mar 15 '20 11:03 payload

+1 setting up a RayCast because of that

mdamien avatar Apr 13 '20 15:04 mdamien

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.

CactusPhD avatar Sep 18 '21 22:09 CactusPhD

Still doesn't work as of 3.4.4.

elvisish avatar Oct 11 '21 22:10 elvisish

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:

Calinou avatar Oct 11 '21 22:10 Calinou

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.

payload avatar Oct 12 '21 17:10 payload

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?

donn-xx avatar Mar 07 '22 10:03 donn-xx

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.

Calinou avatar Mar 07 '22 12:03 Calinou

Still doesn't work as of 4.1

Drazulino avatar Oct 31 '23 04:10 Drazulino

Can confirm that this doesn't work on 4.2.1 either. The documentation concerning this issue is still very misleading.

Waringh4m avatar Feb 28 '24 02:02 Waringh4m

how has this been a bug for 5 years

pillowtrucker avatar Apr 24 '24 20:04 pillowtrucker

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

enbugger avatar Jun 21 '24 22:06 enbugger