:GetGuiObjectsAtPosition() fails to detect any GUI elements whatsoever for some PC users

I use the :GetGuiObjectsAtPosition() function in my game Buckshot Mayhem to detect the GUI buttons that the user’s cursor is currently hovering over which I then use that information to detect the buttons the user is clicking on or just hovering over to play animations on them.

I have been getting reports from my user base that some cannot interact with the game’s UI. After debugging, it turns out that :GetGuiObjectsAtPosition() returns an empty table on those users’ clients while their cursors are hovering over existing GUI elements and the correct Vector2 position is being passed to the function.

Snippet of the code failing to work as expected:

RunService:BindToRenderStep("3DButtons", 100000, function()
	if detected == "Mobile" then
		if Vector2.new(mouse.X, mouse.Y) == lastPos then return end
	end
	
	if not hasMouse then
		if GuiService:IsTenFootInterface() then return end -- Doesn't return as the affected users are on PC devices.
	end
	
	local found = false
	local foundScroll = false
	local objects = playerGui:GetGuiObjectsAtPosition(mouse.X, mouse.Y) -- This function returns an empty table for the affected users.
	
	lastPos = Vector2.new(mouse.X, mouse.Y)

	for _, button in objects do -- This loop does not run when the returned table is empty causing the users to be unable to click/hover on buttons.
		if button == shopScroll then
			foundScroll = true
			
			continue
		end
		
		if not button:IsA("GuiButton") or button:GetAttribute("Animating") == true then continue end
		
		found = true
		
		lastButton.Value = currentButton.Value
		currentButton.Value = button
	end
	
	if not found then
		lastButton.Value = currentButton.Value
		currentButton.Value = nil
	end
	
	canScroll = foundScroll
end)

Video of how the above issue is affecting my user base:

System information of the user experiencing the issue in the above video:

Operating System: Windows 10 Pro
CPU: AMD Ryzen 7 3700X 8-Core Processor
GPU: AMD Radeon RX 5700 XT
Memory Size: 16 GB
Screen Resolution: 1920x1080
Connected Devices:

  • Headset: Razer Kranken
  • Headset Stand: Razer
  • Mouse: Razer Lancehead Tournament Edition
  • Keyboard: Razer BlackWidow V3
  • VR Device: Valve Index Headset (not powered on but plugged in)
  • Other: Body tracking gear

Game Link: [🌟NEW] Buckshot Mayhem - Roblox

Conclusion: The :GetGuiObjectsAtPosition() function returns an empty table while the affected users are hovering over existing GUI objects as seen in the above video. This only happens to a few PC users and the cause is inconsistent/unknown.

Expected behavior

The expected behavior is that the :GetGuiObjectsAtPosition() function returns a table with the GUI elements that overlap the passed Vector2 position for all PC users.

7 Likes

Thanks for the report! We’ll follow up when we have an update for you.

1 Like

Update on the issue:

After investigating further with my the players who come across this bug, I found out that all of them have something in common, which being all of them running Windows 10 as the Operating System on their devices.

If there can be a fix for this soon that would be appreciated, as it’s affecting the potential count of concurrent players my game can get.

I have the same issue but I found out that this function only works if the GUI object’s “Interactable” value is set to false. This is super annoying as this means you can only detect GUI that isn’t clickable/interactable :frowning:

I solved my problem with this function

local function isPointInBounds(Mouse_point, UIElement)
	local AbsolutePosition = UIElement.AbsolutePosition
	local AbsoluteSize = UIElement.AbsoluteSize
	
	local MinX = AbsolutePosition.X
	local MaxX = AbsolutePosition.X + AbsoluteSize.X
	
	local MinY = AbsolutePosition.Y
	local MaxY = AbsolutePosition.Y + AbsoluteSize.Y
	
	if Mouse_point.X >= MinX and Mouse_point.X <= MaxX and Mouse_point.Y >= MinY and Mouse_point.Y <= MaxY then
		return true
		
	else
		return false
	end
		
end

This function has 2 arguments; Mouse_point which is the ‘input.Position’ - basically the mouse’s position, and UIElement which is the GUI element that you are currently checking whether or not your cursor is sharing positions with.

Then I ForLooped through my Frame and checked each object. I only wanted to animate image labels and buttons so I used an if statement to solve that.

The problem with this workaround is that it only works with 2D GUI objects. 3D GUI objects have a variable position since it’s calculated relative to the player’s camera, which basically makes it super difficult to get their accurate position relative to the client’s screen with that workaround.

And if you noticed in the above video I attached to the post, is that the UI is 3D as it’s on a SurfaceGui object.

@CrazyCaptainDEV

I have run into the same issue, I was making 3d ui as well and found mouse enter and mouse leave unreliable.

If you would like to check if the mouse is hovering on a surface gui’s ui element there is a method in this module you can use to get the mouse position on the surface gui. This is the mouse position on the SGUI, not on your viewport. Require the “Methods” module in the hierarchy and use the :GetLocation(SurfaceGui) method.

Then use the method that @Lo_opyy provided. Here is an example:

function isElementUnderMouse(element)
	local mouse = dragMethods:GetLocation(element:FindFirstAncestorOfClass("SurfaceGui"))
	
	local absolutePosition = element.AbsolutePosition
	local absoluteSize = element.AbsoluteSize
	local anchorPoint = element.AnchorPoint
	
	local minX = absolutePosition.X
	local maxX = absolutePosition.X + absoluteSize.X
	local minY = absolutePosition.Y
	local maxY = absolutePosition.Y + absoluteSize.Y
	
	if mouse.X >= minX and mouse.X <= maxX and mouse.Y >= minY and mouse.Y <= maxY then
		return true
	end
	
	return false
end

This allows you to pass any element inside the surface gui and see if the mouse is hovering over it. Hope this helps!

2 Likes