MouseEnter And MouseLeave Not Updating

hi, i am having a issue that the MouseEnter and MouseLeave functions only update when you move your mouse and not when the mouse actually leaves the UI element, as shown here:

is there any workaround to go about this?

I don’t usually do stuff with surface GUIs so here’s the only thing I’m able to recommend:
Since it only checks every time the mouse moves, I would recommend manually checking if it leaves the bounds after entering.

local Mouse = Localplayer:GetMouse() -- locate the localplayer yourself :3
    local Target = Mouse.Target
    if (Target == YourPart) then
        print("mouse entered")
        print("mouse isn't hovering the part")

or if that doesn’t work, use loops and do checks on the Mouse.Target or checks with Camera:ScreenPointToRay()

1 Like

yeah that’s what i was thinking, but i have no clue how to do that

The above post has the answer, there are multiple ways to do it but I’m absolutely sure the above post has the best one.

this would in theory work, but it wouldn’t work with the system i have since it’s using a frame and its having multiple ui elements inside, so im trying to check for the ui elements and not the part

yeah but as i wrote in my recent reply, it wouldnt work due to my system

Just wondering, did you put the surfacegui in StarterGui and set the Adornee to the part? (not very sure if that will solve the issue)

I have it like that in my other game (the main one) but it’s still the same issue

Though quite unreliable, you could use this when mouse has entered.
So basically you have the buttons in a table like so:

local buttons = {
	button1 = surfaceGui.ImageButton,
local mouseInBounds = {}
for name, _ in pairs(buttons) do
	mouseInBounds[name] = false

You’ll use this to get the mouse position ON the part:

local function getMousePositionOnPart()
	local mousePos = Mouse.Hit.p
	local relativePos = part.CFrame:pointToObjectSpace(mousePos)
	return relativePos

And this is the position checking that I was talking about earlier.

local function isMouseOverButton(button, relativeMousePos)
	local buttonPos = button.AbsolutePosition
	local buttonSize = button.AbsoluteSize

	local relativeButtonPos =, buttonPos.Y)
	local mousePos2D =, relativeMousePos.Y)

	return mousePos2D.X >= relativeButtonPos.X and mousePos2D.X <= relativeButtonPos.X + buttonSize.X and
		mousePos2D.Y >= relativeButtonPos.Y and mousePos2D.Y <= relativeButtonPos.Y + buttonSize.Y

I am pretty sure this is not the most optimal solution but I don’t know any better due to my massive lack of 3D on roblox.

Here’s an example on how I would use it.

local function checkMousePosition()
	local relativeMousePos = getMousePositionOnPart()

	for name, button in pairs(buttons) do
		local inBounds = isMouseOverButton(button, relativeMousePos)

		if inBounds and not mouseInBounds[name] then
			mouseInBounds[name] = true
		elseif not inBounds and mouseInBounds[name] then
			mouseInBounds[name] = false


I probably shouldn’t just give this out and just tell you how it’s done, but I’m not good with my words.


yea i thought the same, i just tried to use absolute pos and mouse pos to see if it was inbound or not, it seemed it didnt really work and only worked in some places, and as you said was really unreliable, i’ll try to look for other ways i can acomplish this

I figured it out! It was actually quite simply, all you have to do, is put the SurfaceGui in StarterGui set it’s adornee to the part and in StarterGui add this LocalScript:

local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
repeat task.wait() until LocalPlayer:FindFirstChild("PlayerGui")
local PlayerGui = LocalPlayer:FindFirstChild("PlayerGui")
local Mouse = LocalPlayer:GetMouse()

local Button = script.Parent.SurfaceGui.TextButton

	local GUIObjectsInbound = PlayerGui:GetGuiObjectsAtPosition(Mouse.X, Mouse.Y)
	if table.find(GUIObjectsInbound, Button) then
		print("player is hovering over the button")

you can obviously add onto this but its just a prototype and works perfectly