Hello, All,
I’m currently working on an options menu that has a controller keybind to activate it. When that button is pressed, the menu pops open and sets GuiService.SelectedObject
to the first item in the list. All of this work fine, and I can interact with this first item by pressing A
, but there are some issues:
- The element is not adorned with a selection box to indicate that it is the selected item.
- Once navigated off of, the control cannot be selected again.
Here is a short clip demonstrating my issue:
As for my setup and hierarchy, the controls are organized by their LayoutOrder
using a UIListLayout
, and the placeholders in the example are clones of the affected control (TimerToggle
) with name changes.
All buttons have their Selectable
state set to true
and NextSelectionUp
/NextSelectionDown
set during initialization of the control via this code block:
local options_buttons = {
timer_toggle = {frame = "TimerToggle", button = "TimerButton", selection_control = true},
placeholder1 = {frame = "Placeholder1", button = "Button", selection_control = true},
placeholder2 = {frame = "Placeholder2", button = "Button", selection_control = true},
placeholder3 = {frame = "Placeholder3", button = "Button", selection_control = true},
placeholder4 = {frame = "Placeholder4", button = "Button", selection_control = true},
}
for _,button_specs in pairs(options_buttons) do
button_specs.frame = options_frame:FindFirstChild(button_specs.frame,true)
button_specs.button = button_specs.frame:FindFirstChild(button_specs.button,true)
button_specs.order = button_specs.frame.LayoutOrder
if button_specs.selection_control == true then
--If the gamepad selection point is not the button itself, it needs to be specified with a path.
button_specs.selection_control = button_specs.button
end
button_specs.selection_control.Selectable = true
end
do
local dictionary_sort = require(game:GetService("ReplicatedStorage"):WaitForChild("Utilities"):WaitForChild("TableUtility")).dictionary_sort
local last_selection_control
for _,button_specs in dictionary_sort(options_buttons,function(key1,key2) return options_buttons[key1].order < options_buttons[key2].order end) do
button_specs.selection_control.NextSelectionUp = last_selection_control
if last_selection_control then
last_selection_control.NextSelectionDown = button_specs.selection_control
end
last_selection_control = button_specs.selection_control
end
end
Verification during runtime shows that everything is set as intended, but the above-mentioned behavior is still what I’m seeing.
Here is the code that opens the menu. Again, this has been functioning as intended, as I can interact with the button upon pressing the keybind, meaning that it is selected even though it isn’t showing as selected.
local function options_activate(direct_interact)
control_active = not control_active
if control_active then
enable_tween:Play()
if not direct_interact then --This code will not run if the button was clicked or tapped, only if called by the keybind function.
gui_service.SelectedObject = options_buttons.timer_toggle.selection_control
end
else
disable_tween:Play()
if gui_service.SelectedObject and gui_service.SelectedObject:IsDescendantOf(options_menu) then
gui_service.SelectedObject = nil
end
end
end
I’ve tried moving the control farther from the edge of the screen to no avail, and tests with basic mockups have allowed me to select elements closer to the edge than these elements, so I feel relatively safe disregarding that as a possibility, but beyond that I am stumped. How do I get the gamepad navigator to show that the uppermost control is selected and allow it to be navigated to by the player?