Accurately checking if mouse is within 2D region

Hello there. I’ll make this simple. I have made a system to check if the mouse is within a “2D region,” and although it works, it has one major flaw, it seems like the Y-axis checking is offset. I suspect this is a Roblox bug instead of my code, but regardless, I wanted to ask for help to get it resolved. Here is my code:

-- Services --

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

-- Variables --

local GUI = script.Parent
local RegionsHolder = GUI:WaitForChild("Regions")

-- Functions --

function IsWithinRegion(Pos: Vector2, Region: Frame)
	local TopLeft = Region.AbsolutePosition
	local BottomRight = Region.AbsolutePosition + Region.AbsoluteSize
	
	return (Pos.X >= TopLeft.X and Pos.X <= BottomRight.X and Pos.Y >= TopLeft.Y and Pos.Y <= BottomRight.Y)
end

function GenerateCorners(Region: Frame)
	local TopLeft = Region.AbsolutePosition
	local BottomRight = Region.AbsolutePosition + Region.AbsoluteSize
	
	local BL = Instance.new("Frame", GUI)
	BL.Position = UDim2.fromOffset(TopLeft.X, TopLeft.Y)
	BL.Size = UDim2.fromOffset(10,10)
	BL.BackgroundColor3 = Color3.fromRGB(71, 255, 61)
	BL.AnchorPoint = Vector2.new(0.5, 0.5)
	
	local TR = Instance.new("Frame", GUI)
	TR.Position = UDim2.fromOffset(BottomRight.X, BottomRight.Y)
	TR.Size = UDim2.fromOffset(10,10)
	TR.BackgroundColor3 = Color3.fromRGB(255, 49, 52)
	TR.AnchorPoint = Vector2.new(0.5, 0.5)
end

-- Scripting --

for _, Region: Frame in ipairs(RegionsHolder:GetChildren()) do	
	GenerateCorners(Region)
end

RunService.RenderStepped:Connect(function()
	local MousePosition = UserInputService:GetMouseLocation()
	for _, Region: Frame in ipairs(RegionsHolder:GetChildren()) do
		if IsWithinRegion(MousePosition, Region) then
			Region.BackgroundColor3 = Color3.fromRGB(128, 255, 149)
		else
			Region.BackgroundColor3 = Color3.fromRGB(255, 74, 122)
		end
	end
end)

And here is a GIF of the working product:
https://gyazo.com/8685e3c81b7f9c5a0935d9f1c7da6459

As you can see, it detects that it is “within region” way above the actual region and detects that it is “out of region” while still in the region near the bottom.

If anyone knows how I could solve this, that would be amazing. Thank you for your time and help, I truly appreciate it.

1 Like

Why aren’t you using GuiObject.MouseEnter? They are UIs so why do all of that?

Well, the point is to not be using GUI objects in the end, so I need to make it work with positions. My question still remains on how I check the region accurately. I assume this has to do with the mouse position not matching with the UI one.

1 Like

In the IsWithinRegion() function you need to account for the GuiInset (topbar) for your corner positions.

The :GetMouseLocation() position doesn’t take into account the topbar. So if your mouse is at the top of the screen at the very top of the topbar, it would be 0 on the Y axis while a frame set to 0 on the Y axis will appear underneath the topbar. Both the mouse position and the TopLeft position would read as 0, thinking they are within the same region even though the mouse is above it in the topbar.

You can fix this by adding Vector2.new(0,TopbarHeight) (I think the top bar is 36-40 pixels tall) or you can set your ScreenGui’s IgnoreGuiInset property to true which will move all of your frames up, ignoring the topbar padding.

3 Likes

Yep, that worked nicely. Topbar is indeed 36 pixels, so I just subtracted Vector2.new(0, 36) from the mouse position and now it works as intended. Thank you so much for the notice, really helped.

1 Like