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:
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.
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
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.
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!