Rewrite GetMouseDelta() to work with unlocked cursor

As a Roblox developer, it is currently too hard to consistently get the mouse’s movement delta due to the fact that GetMouseDelta() defaults to returning (0,0) if the mouse is unlocked (e.g. third person camera; modal Gui enabled).

Developers should always be able to expect GetMouseDelta() to return the raw mouse delta regardless of cursor locking. Unless there’s a specific technical limitation that prevents this, it doesn’t make sense to me that it would only work while the cursor is not actually moving.

If Roblox is able to address this issue, it would improve my development experience because getting the mouse’s movement should be as straightforward as the function’s name implies, not necessitating me to write my own delta calculator for instances when the player’s cursor is unlocked.

21 Likes

I suspect maybe the reason for GetMouseDelta only working if the mouse is locked is likely because of the way the locking behaviour is done in the first place (e.g. Roblox is querying an input API that handles the locking, and that API is designed specifically for the mouse lock).

I agree though, it would be much nicer to be able to access the raw mouse delta on the current frame without having to connect an event. The current behaviour is likely confusing.

Here’s a nice way to measure mouse delta synchronously (e.g. if you have a frame loop or something):

local UserInputService = game:GetService("UserInputService")
local oldMousePosition = UserInputService:GetMouseLocation()
local function getMouseDelta()
	-- Measure mouse position & delta since last measurement
	local mousePosition = UserInputService:GetMouseLocation()
	local delta = mousePosition - oldMousePosition

	-- Update the old mouse position & return the delta
	oldMousePosition = mousePosition
	return delta
end

If you want asynchronous delta that’s per frame rather than per measurement, you do have to connect an event to mouse moved (you can convert the above into a per-frame measurement just by calling getMouseDelta() per frame and storing it in a local variable)

6 Likes

Can’t you just do something like this??

local RunService,UserInputService = game:GetService("RunService"),game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()

local Prev

RunService.Heartbeat:Connect(function()
	local Pos = Vector2.new(Mouse.X,Mouse.Y)
	
	local Delta = Pos - (Prev or Vector2.new()) + UserInputService:GetMouseDelta()
	
	print(Delta)
	
	Prev = Pos
end)

So basically it combines the difference in pixels on screen that the mouse has moved with GetMouseDelta(), meaning that it will return the mouse delta regardless of if it’s locked or not.

5 Likes

just what I literally was looking for for days now thank you so much :smile: