BillboardGUI ImageButtons not consistently firing MouseLeave

Everything is working fine, except that the tooltips that are meant to show when their parent is hovered over don’t always disappear.
The structure of the BillboardGUI in question is:

BillboardGUI (Active)
	Thumbnail (Inactive, fills GUI)
	Button1 (Active, fills top-right quarter of GUI, layer 2)
		Tooltip (Inactive, bottom of button)
	Button2 (Active, fills bottom-right quarter of GUI, layer 2)
		Tooltip (Inactive, bottom of button)

Button1 has a 50:50 chance of firing MouseLeave if the mouse leaves it and enters BillboardGUI (whether it goes straight from the button to the GUI or exits then re-enters the GUI). The other button is treated the same as the rest of the GUI.
Button2 is the same, except that the other button is not treated the same as the GUI, moving from Button2 to Button1 will not trigger MouseLeave.

Entering another BillboardGUI will never trigger MouseLeave.

Yeah, MouseLeave overall is really iffy. I wouldn’t recommend relying on it, especially not for gameplay. For now, I’d recommend periodically manually checking if the mouse is inside of the object.
https://devforum.roblox.com/t/mouseleave-event-doesnt-work-all-the-time/9045
https://devforum.roblox.com/t/mouseleave-doesnt-fire-if-you-move-mouse-fast/121169
https://devforum.roblox.com/t/mouseenter-and-mouseleave-are-extremely-glitchy/25777

That was my first idea for a solution, but the ImageButton class doesn’t seem to offer a way of checking mouse presence.

Yeah, you have to do it manually. You can use these things to figure it out:
X and Y of the mouse
AbsolutePosition and AbsoluteSize of the button

You could use Button.InputBegan and Button.InputEnded with the UserInputType MouseMovement as an easier solution.

I can’t get the AbsolutePosition of the button, it’s measured relative to the BillboardGUI (which always has an AP of 0,0).

Wouldn’t input end as soon as the mouse stopped moving?

I’ve ran into problems with quickly moving my mouse from one element to the next before. The way I resolved this was by having a variable hold the previous button.

   local HoveredButton  = {Element = nil, DisconnectFunction = nil}
   local Button1        = script.Parent.Button1
   local BillboardGuiButton   = game.Players.LocalPlayer.PlayerGui.BillboardGui.Button

   Button1.MouseEnter:Connect(function()
      if HoveredButton.Element and HoveredButton.Element ~= Button1 then
         HoveredButton.DisconnectFunction()
      end 
      HoveredButton.Element = Button1 
      HoveredButton.DisconnectFunction = function()
          -- Behavior that will visually show that we left the button
          Button1.Position = UDim2.new(1,0,1,0)
      end
      -- Now we do something with this button. :)  
    end)

    BillboardGuiButton.MouseEnter:Connect(function()
      if HoveredButton.Element and HoveredButton.Element ~= BillboardGuiButton then
         HoveredButton.DisconnectFunction()
      end 
      HoveredButton.Element = BillboardGuiButton 
      HoveredButton.DisconnectFunction = function()
          -- Behavior that will visually show that we left the button
           BillboardGuiButton .Position = UDim2.new(1,0,1,0)
      end
      -- Now we do something with this button. :)        
    end

If all of your buttons have the same behavior then you could store them all in a table and just iterate through all of the elements with the example code above. This is how I get around the silly MouseLeave Event. But the downside to this is that since there is no MouseLeave Event, the button won’t know if you left it, only when you enter another button.

It doesn’t; trust me, I’ve used it for many UIs.

Remember that this is all in the context of the button, knowing when the mouse stops moving while still on it wouldn’t really have any use.

1 Like

But the mouse not moving isn’t input, and you’re saying to hide the tooltip when input ends.
I think you’ll have to show me the code you used.

Like I said, it’s in the context of the button. Normal UserInputService would have stopped the MouseMovement input, but since it’s in the context of a button (where the only obvious use is for hover detection), Roblox made it so that when the mouse stops moving (and is still on the button), the ended event doesn’t fire. It’s a quality of life thing.

Here’s an example:

Button.InputBegan:Connect(function(Input)
    if Input.UserInputType == Enum.UserInputType.MouseMovement then
        -- do hover animation
    end
end)

Button.InputEnded:Connect(function(Input)
    if Input.UserInputType == Enum.UserInputType.MouseMovement then
        -- do unhover animation
    end
end)```

I got exactly the same results from that.
Maybe I’ll just have no tooltips, it’s not like they’d work for the 50% of players that don’t use PCs.

Ah, then you have encountered the same issue I have.

It was working as a solution to the issue for … well, ever, until about 3 weeks ago: