GetMouseLocation and GetMouse returning inaccurate positions

When moving the mouse quickly and then suddenly holding right-click, both GetMouseLocation() and Player:GetMouse() begin returning incorrect positions that no longer match the visible location of the mouse cursor. The values remain desynced until left-click is pressed, which temporarily corrects the issue. However, moving the mouse again while still holding right-click causes the desync to return immediately.

Repro:
mouseDesyncRepro.rbxm (3.6 KB)

Expected behavior

These methods should consistently return the actual, visible position of the mouse cursor. Alternatively, there should be a reliable method provided to accurately track the real-time mouse position, allowing for precise custom crosshair implementations.

2 Likes

Thanks for your report.
Does this occur on UWP Windows for you?

Many users have reported this issue, I was able to replicate it on Windows 10 using the regular Roblox app.

I reproduced this behavior in MousePosTest - Roblox.
From what I can tell, you are observing 3 things:
a) the mouse cursor is drawn by windows, not the game, so it’s framerate independent
b) the grey box renders per frame, meaning it lags behind the mouse cursor
c) the “GetMouseLocation” stops updating when you right click, because we technically freeze the mouse position and update the camera instead

So what you are observing is not “the wrong mouse location”, but that the “real mouse location at game time” is lagging behind the hardware cursor.
This is technically not a bug, but it sounds what you are looking for is that the mouse location updates one more time after you right-clicked to move the camera?

Hold on, I think I’m misinterpreting this.

To explain this from a different angle: if Roblox would draw the mouse cursor, it would be where the grey box is. The problem is there is a mismatch between the internal mouse location and the HW mouse location at the time you “freeze” the location with right click.

1 Like

This explanation has helped, thank you.

Seems like there is something causing a desync between what the engine sees and what the OS sees.

The engine is able to, when the bug isn’t occurring, switch back to where the OS cursor is, so all I can infer/strongly guess is that the engine has different values or methods that it pulls the cursor info from based on its state and it’s only being updating in generic cases ie. cursor location updates.

Yeah, I assumed that would be the case. I’ve also noticed that changing the Mouse Icon property resolves the lag, likely due to its native support.

Can you suggest any workarounds to align the crosshair with the hardware cursor position, while supporting our multi-element design? This issue is affecting our PvP gameplay, especially for players who hold right-click to aim and shoot.

2 Likes

Hey @rip_indra quick update: we are investigating whether there are any viable workarounds for you and/or whether any engine-side changes would be warranted to help. Oddly enough, the HW cursor was employed to help responsiveness in situations where frame rate impacts input processing, such as cursor position updates.

Hi there, can you explain your use case more for us to suggest a workaround? If you have a crosshair icon, you can use the Mouse Icon property to change the hardware cursor’s icon to the crosshair. Or if you want to use the engine’s mouse location, you can manually update the cursor’s location like in your repro file and turn off the hardware mouse icon with MouseIconEnabled. This sacrifices a bit of mouse responsiveness, but will use the engine’s mouse location which will be more accurate for hover and other mouse position effects.

1 Like

If you have a crosshair icon, you can use the Mouse Icon property to change the hardware cursor’s icon to the crosshair

Yep, using the Mouse Icon property isn’t an option - we use an image as a custom cursor and toggle UserInputService.MouseIconEnabled because we want granular control over different aspects of the cursor, such as animating it (rotating/spinning the icon while you’re firing the gun, and while reloading) and easily overlaying other mechanically relevant UI elements (Frames & TextLabels) on top of it to indicate reload states and “overheat” states on certain guns.

So we’re already doing your proposed solution of manually updating the custom cursor location every frame and turning MouseIconEnabled off. The problem as rip_indra described in the OP is that none of the available engine methods seem to provide a truly accurate read on the engine’s mouse location in the described scenario, or rather as @MetaVars described

the “GetMouseLocation” stops updating when you right click, because we technically freeze the mouse position and update the camera instead

And what MetaVars said seems to be the behavior we would expect, to avoid this flickering issue

This is technically not a bug, but it sounds what you are looking for is that the mouse location updates one more time after you right-clicked to move the camera?

1 Like

Hi there! Thanks for all the details. To be clear, the software mouse position (the one returned by GetMouseLocation) is actually the one used by the engine for all mouse effects such as UI hover and click detectors. The hardware location of the cursor exists to improve the responsive feel of mouse movements. Fixing the software cursor to align with the hardware cursor would involve speeding up input processing in the engine. We have plans in the works, but this is a very comprehensive and lengthy project.

We’ve been looking into smaller fixes such as pulling the hardware cursor back to the software location on right click, or letting the software continue to update for a couple of frames after hardware freezes, but these all have issues will visible jumps and will cause problems in other games using hardware cursor.

Hey, thank you for the response. This is our code from the repro:

local UserInputService = game:GetService("UserInputService")

-- local mouse = game.Players.LocalPlayer:GetMouse()
local function updatePositions()
    -- adding `UserInputService.MouseIconEnabled = false` here doesn't help
	local mouse = UserInputService:GetMouseLocation() - Vector2.new(0, game.GuiService.TopbarInset.Height)
	
	script.Parent.Position = UDim2.fromOffset(mouse.X, mouse.Y)
end

game:GetService("RunService").RenderStepped:Connect(updatePositions)

It’s functionally equivalent to our code in game, just stripped down a bit. MouseIconEnabled is false, and when setting it to false in the repro file, the issue still persists. Is there anything at all that we can be doing to alleviate the described issue and get the functionality we want? It sounds to me like there’s not right now since this is an engine issue.