Is there a better way to know if the mouse is hovering a button?

I wanted to know if there is a better way to know if the player mouse started hovering a button without using: button.MouseEnter or button.MouseLeave

I want to know it because I think writing a “button.MouseEnter:Connect(function()” for everysingle button pretty unoptimized.

Using button.MouseEnter and button.MouseLeave for many buttons is perfectly fine, but you don’t have to manually assign the connections to individual buttons. If you have many similar buttons, I recommend using a loop to assign connections to all the buttons.

For example, rather than doing this:

local button1 = script.Parent.Buttons.Button1
local button2 = script.Parent.Buttons.Button2
local button3 = script.Parent.Buttons.Button3

button1.MouseEnter:Connect(...)
button2.MouseEnter:Connect(...)
button3.MouseEnter:Connect(...)

button1.MouseLeave:Connect(...)
button2.MouseLeave:Connect(...)
button3.MouseLeave:Connect(...)

You could do this instead:

local buttons = script.Parent.Buttons

for _, button in pairs(buttons:GetChildren()) do
	button.MouseEnter:Connect(...)
	button.MouseLeave:Connect(...)
end

Let me know if you need further assistance.
Happy scripting!

2 Likes

Yes, use GuiState property with changed connection.

MouseLeave = Button:GetPropertyChangedSignal('GuiState'):Connect(function() 
	--USE GUISTATE SINCE MOUSELEAVE IS BUGGY AND DOESNT FIRE FOR TWEENS/VISIBILTIY CHANGES
	if Button.GuiState ~= Enum.GuiState.Hover then 
		--YOUR CODE 
	end
end)

Interesting. Today I learned this property exists and can be used this way. However, this code is not a 1:1 replacement for MouseLeave. When reading GuiState’s API reference, it’s shown that there can only be one state. This is common among finite state machines. If the user enters any other state while hovering over the GUI, for example, the “Press” state when pressing the GUI, this code will believe the user stopped hovering.

I developed my own replacement a while back, but even that’s not a 1:1. It’s flaw is that it only considers the GuiObject directly under the cursor, missing buried GuiObjects that are technically still intersecting with it