Bug Summary
Buttons and .Active GuiObjects do not sink mouse and touch control input consistently:
- gameProcessedEvent is false for an inactive Button with touch controls yet true for an inactive Button with mouse controls
- InputBegan and InputEnded do not fire/refrain from firing for non-top-most Buttons or .Active GuiObjects consistently (see the Observable Behaviour from Script section below)
- InputChanged always fires, which is inconsistent compared to InputBegan/InputEnded
Recreation Steps
Put the following code in a LocalScript in the StarterGui in an otherwise blank place and play solo, then click and drag where the buttons overlap using the mouse or touch controls.
local active, guiType = false, "TextButton" -- configure these to explore different cases
local screenGui = Instance.new("ScreenGui")
screenGui.Parent = script.Parent
local function new(y)
local b = Instance.new(guiType)
b.Active = active
b.Size = UDim2.new(0, 200, 0, 100)
b.Position = UDim2.new(0, 0, 0, 67 * (y-1))
b.Parent = screenGui
b.InputBegan:Connect(function() print("b" .. y .. ".InputBegan") end)
b.InputChanged:Connect(function() print("b" .. y .. ".InputChanged") end)
b.InputEnded:Connect(function() print("b" .. y .. ".InputEnded") end)
return b
end
local b1, b2 = new(1), new(2)
local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
print("UIS.InputBegan | Processed:", gameProcessedEvent)
end)
game:GetService("UserInputService").InputChanged:Connect(function(input, gameProcessedEvent)
print("UIS.InputChanged | Processed:", gameProcessedEvent)
end)
game:GetService("UserInputService").InputEnded:Connect(function(input, gameProcessedEvent)
print("UIS.InputEnded | Processed:", gameProcessedEvent)
end)
Observable Behaviour from Script
Results of clicking on the overlap between the buttons and dragging:
(UserInputService's InputBegan/Changed/Ended events always fire)
TextButtons:
active = false:
touch controls:
gameProcessedEvent is false
all events fire for both buttons
mouse controls:
gameProcessedEvent is true for InputBegan and InputEnded but false for InputChanged
only the button on top fires for InputBegan and InputEnded, but InputChanged fires for both
active = true:
touch controls:
gameProcessedEvent is true
only the button on top fires for InputBegan and InputEnded, but InputChanged fires for both
mouse controls:
gameProcessedEvent is true
only the button on top fires for InputBegan and InputEnded, but InputChanged fires for both
Frames:
active = false:
touch controls:
gameProcessedEvent is false
all events fire for both frames
mouse controls:
gameProcessedEvent is false
all events fire for both frames
active = true:
touch controls:
gameProcessedEvent is true
only the button on top fires for InputBegan and InputEnded, but InputChanged fires for both
mouse controls:
gameProcessedEvent is true
all events fire for both frames
Tested TextButtons in Play Solo, Test Local Server, and Online modes
Expected Behaviour
- Consistency between mouse and touch controls
- Consistency between InputBegan/InputEnded and InputChanged
- For overlapping GuiObjects, the top .Active GuiObject should either:
- never prevent the other GuiObjects from firing InputBegan/Changed/Ended events (based on the Active page, where it says “The events InputBegan, InputChanged, and InputEnded work as normal no matter the value of this property.”)
- always prevent the other GuiObjects from firing InputBegan/Changed/Ended events if its Active property is true (based on the GuiObject page where Active’s summary is “Determines whether a UI element sinks input”)
Benefits if only the top .Active GuiObject fires InputBegan/Changed/Ended events
The documentation isn’t clear whether the intended behaviour is for the top .Active GuiObject being the only one to fire InputBegan/Changed/Ended events. Reasons I think this behaviour is desirable:
- Active frames could act as movable/resizable “windows”. Windows (like shop menus), popups, and confirmation messages could all easily be used/shown to the player without having to hide all guis that might overlap with whatever the player is actively interacting with. Further, the player could be allowed to resize any gui without concern that, while interacting with the top gui, the player will accidentally also click (or activate an on-hover event) on something beneath it
- When a player hovers over two active buttons with AutoButtonColor enabled, Roblox would no longer change the colour of both buttons (making it look much more professional if the buttons are both at least partially visible).
Bug Age
I’m unsure if this was ever working as intended
Bug Report Limitations
I have only tested it on Windows (including with the in-studio touch device emulator) and have not tested:
- controllers
- GuiObject.Activated event
- If the input was correctly prevented from going into the 3D world (ex into a ClickDetector)