How to detect if the player moused over a GUI button?

Well, I want to detect if the player moused over any GUI button, so I can change the color of the GUI button itself. I thought using Mouse.Target:ChildAdded would work, but apparently not.
Even though I tried the Mouse.Target thing, it didn’t work

local players = game:GetService("Players")
local player = players.LocalPlayer
local Mouse= player:GetMouse()
local Target = Mouse.Target 

Target.ChildAdded:Connect(function(obj)
	print(obj.Name)
end)
1 Like

You can use GuiObject.MouseEnter and GuiObject.MouseLeave for this.

1 Like

I know, but it seems to me that it is not something that is very optimized for buttons, because I would have to use a cycle for each menu with buttons

mouse.Target is for BaseParts. If you don’t want to use .MouseEnter and .MouseLeave, you can try BasePlayerGui:GetGuiObjectsAtPosition

Then iterate through the UI objects, add the objects that are GuiButtons to another table, and that table will contain all buttons at the mouse’s position.

2 Likes

I did this, but now I don’t know how to time it so that when I move the mouse off the button (I want to make a color animation of the buttons that is whiter when the mouse is on the button and the opposite if it’s not on the button)

local player = players.LocalPlayer
local PlayerGui = player.PlayerGui

local Button

UserInputService.InputChanged:Connect(function(input, gameProcessed)
	local pos = input.Position
	
	local guisAtPosition = PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y)
	
	if PlayerGui ~= nil then
		for index, obj in pairs(guisAtPosition) do
			if obj:IsA("GuiButton") then
				Button = obj
				print(obj.Name)
			end
		end
	end
end)

I tried to do it like this, but it doesn’t seem to work

local player = players.LocalPlayer
local PlayerGui = player.PlayerGui

local Button = nil

UserInputService.InputChanged:Connect(function(input, gameProcessed)
	local pos = input.Position
	
	local guisAtPosition = PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y)
	
	if PlayerGui ~= nil then
		for index, obj in pairs(guisAtPosition) do
			if index >= 1 and Button == nil and obj:IsA("GuiButton") then
				Button = obj
				print(obj.Name)
			elseif index == 0 and Button ~= nil then
				print("wwww")
				Button = nil
			end
		end
	end
end)

I forgot to set the Button variable to nil.
Edit 3: No, it still doesn’t work

I would probably do it on mouse.Move, although userInputService.InputChanged should work as well, but you should check that the InputType is MouseMovement.

I would also save a table of the previous GuiButtons to compare them, so we can know what objects are there that weren’t previously, and we can know what was previously there that isn’t currently.

local last = {}
userInputService.InputChanged:Connect(function(input, gameProcessed)
	local pos = input.Position
	if gameProcessed or input.UserInputType ~= Enum.UserInputType.MouseMovement then
        return
    end
	local guisAtPosition = PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y)
    local buttonsAtThisPosition = {}
    for i,v in ipairs(guisAtPosition) do
        if not v:IsA('GuiButton') or table.find(last, v) then -- this button is in the current iteration, and it was in the last iteration so to reduce a useless assignment, let's skip
            continue
        end
        table.insert(buttonsAtThisPosition, v)
        -- assign its colour here
    end	
    for i,v in ipairs(last) do -- now, let's handle the buttons that were there on the last iteration that aren't at the mouse's position on this iteration
        if not table.find(buttonsAtThisPosition, v) then
            -- assign its colour here back to the default colour, it the mouse isn't hovering over it
        end
    end
    last = buttonsAtThisPosition -- now we need to assign this new table of buttons to be compared on the next iteration
end)
1 Like

for some reason it didn’t work for me, but it worked for me removing the first condition

local last = {}
UserInputService.InputChanged:Connect(function(input, gameProcessed)
	local pos = input.Position
	local guisAtPosition = PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y)
	local buttonsAtThisPosition = {}
	for i,v in ipairs(guisAtPosition) do
		if not v:IsA('GuiButton') or table.find(last, v) then --este botón está en la iteración actual, y estaba en la última iteración, así que para reducir una asignación inútil, saltemos
			continue
		end
		table.insert(buttonsAtThisPosition, v)
		-- se asignan los colores aquí
		TweenService:Create(v, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(5, 5, 5)}):Play()
	end	
	for i,v in ipairs(last) do --ahora, manejemos los botones que estaban allí en la última iteración que no están en la posición del mouse en esta iteración
		if not table.find(buttonsAtThisPosition, v) then
			-- asigne su color aquí de nuevo al color predeterminado, si el mouse no está sobre él
			TweenService:Create(v, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(5, 56, 89)}):Play()
		end
	end
	last = buttonsAtThisPosition -- ahora necesitamos asignar esta nueva tabla de botones para compararla en la próxima iteración
end)

UserInputService.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.E then
		--ReplicatedStorage.RemoteEvent:FireServer()
	end
end)

There is a problem, apparently how the color of the button gets saturated when you mouse over it, and sometimes it doesn’t go back to the default color

UserInputService.InputChanged:Connect(function(input, gameProcessed)
	local pos = input.Position
	if not gameProcessed or input.UserInputType ~= Enum.UserInputType.MouseMovement then
		return
	end
	local guisAtPosition = PlayerGui:GetGuiObjectsAtPosition(pos.X, pos.Y)
	local buttonsAtThisPosition = {}
	for i,v in ipairs(guisAtPosition) do
		if not v:IsA('GuiButton') or table.find(last, v) then --este botón está en la iteración actual, y estaba en la última iteración, así que para reducir una asignación inútil, saltemos
			continue
		end
		table.insert(buttonsAtThisPosition, v)
		-- se asignan los colores aquí
		TweenService:Create(v, tweeninfo, {BackgroundColor3 = Color3.fromRGB(5, 5, 5)}):Play()
	end	
	for i,v in ipairs(last) do --ahora, manejemos los botones que estaban allí en la última iteración que no están en la posición del mouse en esta iteración
		if not table.find(buttonsAtThisPosition, v) then
			-- asigne su color aquí de nuevo al color predeterminado, si el mouse no está sobre él
			TweenService:Create(v, tweeninfo, {BackgroundColor3 = Color3.fromRGB(5, 56, 89)}):Play()
			print"asd"
		end
	end
	last = buttonsAtThisPosition -- ahora necesitamos asignar esta nueva tabla de botones para compararla en la próxima iteración
end)

Sorry I went to sleep after posting that.

I might see the issue, it your condition should be if gameProcessed, not if not gameProcessed. gameProcessed is only true if there’s something like a textbox being focused, Roblox menu being opened etc.

Looking back at it, you shouldn’t need the gameProcessed condition because I’d assume you would want the button to change colours regardless of whether something’s in the way or not. So try this instead:

    if input.UserInputType ~= Enum.UserInputType.MouseMovement then
		return
	end
local pathtobuttons = script.Parent.Frame

for i,child in ipairs(pathtobuttons:GetChildren()) do
			if child:IsA("TextButton") or child:IsA("ImageLabel") then
				child.MouseEnter:Connect(function()
					-- color stuff here
				end)
				
				child.MouseLeave:Connect(function()
					-- color stuff here
				end)
			end

ik im late lol