Fix Mouse Position Lag

Godot Version

4.2.2

Question

One basic problem I’ve been running into a lot with Godot is properly using the mouse position. For some reason there seems to be a slight delay between the position being used and the actual mouse position.
Here’s a basic example:


The Godot logo is using this code to move to the mouse position:

func _process(delta):
	position = get_window().get_mouse_position()

The arrow is using this code to point towards the mouse:

func _process(delta):
	look_at(get_window().get_mouse_position())

I can’t figure out why both objects are lagging behind the mouse, or how to fix it.

2 Likes

can you try to use get_global_mouse_position() instead of get_window().get_mouse_position()?

I just tried that but it unfortunately doesn’t change anything.

can you put this code in _physics_process()?

That doesn’t seem to work either.

Thats weird. Are there any changes you made in this project or is this an empty project with just does two lines of code?

This is inherent to how the OS mouse cursor is drawn compared to any other window, and is not an issue exclusive to Godot. You can’t fix this entirely unless you replace the mouse cursor image with the sprite’s texture, which you can do using OS.set_custom_mouse_cursor(). The arrow will still appear to lag behind slightly though, which you could mitigate by making look_at() point towards the extrapolated (predicted) mouse cursor’s position instead of its current mouse position. Doing so will introduce some visible error when the mouse cursor speed changes quickly though, so the result may look shaky in motion.

If you can’t use hardware mouse cursors for some reason, see the suggestions to reduce Input lag in the documentation.

5 Likes

Hi! Sorry for bringing up this old topic, but I just ran afoul of this issue and got curious as to WHY exactly this is happening. I also checked that this happens in basically every app with drag support that I could think of (Google Maps in Chrome, Windows Photos, Paint.NET, etc). If you know more, could you please point me in some direction that explains this issue? I know I won’t be able to solve it without drawing my own mouse cursor - I just want to understand what’s going on here. :slight_smile:

The operating system’s compositor draws the mouse cursor in a way that does not require V-Sync to avoid tearing, but without the added latency that V-Sync normally incurs. I am not 100% sure what specifics are involved here (which is possibly OS-specific too), but keep in mind triple-buffered V-Sync (the default in Godot and most other engines) adds 2 frames of latency, while double-buffered V-Sync adds 1 frame of latency. Double-buffered V-Sync will drop frames much more noticeably if the target framerate can’t be reached, so it’s generally only favored in situations where you know you can reliably reach the target framerate (e.g. rhythm/fighting games).

If you disable V-Sync, the software cursor position should roughly match the hardware cursor position, but you will get tearing that is noticeable when scrolling.

The OS could in theory introduce a frame delay to the hardware cursor so it matches the software cursor position, but it would feel a lot less pleasing to use as all mouse interactions would feel noticeably delayed (not just those involving a software cursor).

PS: When I use the term “software cursor” above, I refer to the cursor position seen by Godot (or any other app), not necessarily a sprite that is programmed to follow the mouse cursor. This affects drag-and-drop previews as well as panning.

1 Like