Gamepad input still makes UIPageLayout change frames when selected button is moved off-screen/destroy despite GamepadInput being disabled?

So for context, our game’s main UI is in a UIPageLayout. We have a top bar that users can tap/click/use controller input to switch. Tap and clicking the button works as expected, the gamepad can select buttons or use L1 or R1 to proceed to the previous and next page respectively.

For some reason, when a new UI appears on screen, the controller input freaks out and puts me on a random page, I’m not pressing L1 or R1, Gamepad, Touch, and ScrollWheelInput are all false so it shouldn’t be scrolling, right? Does anyone have any ideas why this is happening and/or how to fix?

As you can see in this video, I bought a crate and it freaked out and put me on the Equip page. Then, when I pressed claim, it put me on the teleports page? You can tell I don’t intend to do this as the highlight thing at the top doesn’t move.

Binds are created in the InputManager module which is basically a UserInput/ContextActionService wrapper that ensures inputs are valid and whatnot. I’m just completely lost. I’ve added a print inside of the function that switches which page the user is on and nothing.

Relevant parts from the TopBarSwitcher script:

function module:Focus(nameToFocus: string)
	if nameToFocus == self.SelectedName then
	print('switching page') -- only prints when I expect it to again
	local frameInfo = assert(self._buttons[nameToFocus])
	self.SelectedName = nameToFocus
	(self._uiPageLayout :: UIPageLayout):JumpTo(frameInfo.Frame)
		self._highlight,, self._uiPageLayout.EasingStyle, self._uiPageLayout.EasingDirection), 

function module:CreateBinds()
	self = self :: TopBarSwitcher
	framework.inputManager:BindAction('TopBarSwitcherKeybind', function(name, state, inputObject)
		if state ~= Enum.UserInputState.Begin then
		print('switching?') -- prints only when I expect it to
		if inputObject.KeyCode == Enum.KeyCode.ButtonL1 then
		elseif inputObject.KeyCode == Enum.KeyCode.ButtonR1 then
		return Enum.ContextActionResult.Sink
	end, { Enum.KeyCode.ButtonL1, Enum.KeyCode.ButtonR1 })

To create a crate spinner UI:

function module:CreateCrateSpinner(crateInfo: { CrateGUID: string; ActualObject: string; Coins: number?; DecoyObjects: {string}; Dupe: boolean? }, crateType: string, backgroundColour: Color3)
	local newCrate = openingCrate:Clone()
	local itemsContainer = newCrate:WaitForChild('Items')
	local clipBounds = itemsContainer:WaitForChild('ScrollingFrame'):WaitForChild('ClipBounds')
	local uiPageLayout = clipBounds:WaitForChild('UIPageLayout')
	local realItemData = framework.itemData.Halos[crateInfo.ActualObject] or framework.itemData.Trails[crateInfo.ActualObject] or framework.itemData['Particle Effects'][crateInfo.ActualObject]

	local newLabel = createItemLabel(realItemData) -- function that creates a frame for the cosmetic that should be shown in the spinner
	newLabel.LayoutOrder = 20

	for i = 19, 1, -1 do -- ^same as above but for the decoy objects
		local thisDecoy = crateInfo.DecoyObjects[i]
		local foundItemData = framework.itemData.Halos[thisDecoy] or framework.itemData.Trails[thisDecoy] or framework.itemData['Particle Effects'][thisDecoy]
		local itemLabel = createItemLabel(foundItemData)
		itemLabel.LayoutOrder = i
		itemLabel.Parent = clipBounds

	newLabel.Parent = clipBounds
	newCrate.Parent = framework.MainUI

	local button = uiController:GetUIModule('ButtonGeneric').new(newCrate:WaitForChild('Spin')) -- create a button controller for the spin button
	local colour = framework.shopInfo.RarityColours[crateType] -- get colours and whatnot for theming
	newCrate:WaitForChild('Background').BackgroundColor3 = backgroundColour
	newCrate:WaitForChild('Sides').BackgroundColor3 = backgroundColour
	newCrate.BackgroundColor3 = backgroundColour
	newCrate:WaitForChild('UIStroke').Color = colour
	newCrate:WaitForChild('TitleContainer'):WaitForChild('TitleMain').Text = CRATE_TITLE:format(colour:ToHex(), crateType)
	tweenService:Create(newCrate,, Enum.EasingStyle.Bounce, Enum.EasingDirection.Out), {Position = UDim2.fromScale(.5, .5)}):Play() -- part where the frame should go on-screen

	fadeIn(button) -- fade in the spin button
	button.MouseButton1Click:Wait() -- in the button controller, a custom click event is created so I can control when the input should be created
	fadeOut(button) -- fade out the fade in button
	task.delay(0.5, button.Destroy, button)

	tweenService:Create(clipBounds,, {AnchorPoint =, 0.95), 0.5)}):Play() -- to simulate a random offset
	uiPageLayout:JumpToIndex(99) -- finally, spin

	local titleContainer = newCrate:WaitForChild('TitleContainer')

	local now = tick()

    -- irrelevant part omitted 

	local youGotLabel = itemsContainer:WaitForChild('YouGot')
	youGotLabel.Text = formatYouGot(realItemData, crateInfo.Dupe) -- set the text
	tweenService:Create(youGotLabel,, {TextTransparency = 0}):Play()
	local okayButton: types.ButtonGeneric, equipButton: types.ButtonGeneric = 
	if crateInfo.Dupe then
		okayButton._frameRef.Position = UDim2.fromScale(0.5, 0.9)
		equipButton._frameRef.Visible = false
	local yieldSignal = -- wait until one of the buttons has been clicked
	local okConnection = okayButton.MouseButton1Click:Connect(function()
	local equipConnection = equipButton.MouseButton1Click:Connect(function()
		yieldSignal:Fire()'EquipCosmetic', { ToEquip = true; Name = crateInfo.ActualObject})
	yieldSignal:Wait()'CrateFireServer', { GUID = crateInfo.CrateGUID }) -- to stop waiting for the client to spin the crate
	tweenService:Create(newCrate,, Enum.EasingStyle.Back), { Position = UDim2.fromScale(0.5, -0.5) }):Play() -- move crate off-screen and destroy crate frame
	task.delay(1, newCrate.Destroy, newCrate)

Does anyone have any ideas?

1 Like

Bumping, I’m still stumped on how to go about fixing.

I suppose I could just disable all the buttons that shouldn’t be selectable with a loop, however this seems very hacky.