Auto scrolling to a selected UI element?

Is there an example of a recommended way to handle scrolling to a selected UI item for controller navigation? I’ve recently run into this problem and have been experimenting with ways to solve it.

You are probably looking for ScrollView.ScrollTo. It needs the element in parameter and it will scroll to it, assuming it lives in the ScrollView.

1 Like

Isn’t that only for UItoolkit? Good to know it has a solution tho :thinking:

Yes, I assumed you were working with UI Toolkit based on the title, sorry. For uGUI, I think you can use what is suggested here: user interface - How to scroll to a specific element in ScrollRect with Unity UI? - Stack Overflow

Yeah i tried that one but it’s really jank. Needs a lot of additional stuff. Plus need to separate it from mouse input, etc.

I’ve posted code that centers an element in a scroll view here:

You can call it in ISelectHandler.OnSelect to center an item when it’s selected through navigation.

public void OnSelect(BaseEventData eventData)
{
    var scrollRect = GetComponentInParent<ScrollRect>();
    if (scrollRect != null) {
        scrollRect.ScrollToCenter(transform as RectTransform);
    }
}

I think you can check if the eventData is a PointerEventData instead of a AxisExtentData to filter out selection through mouse/touch.

But I use a custom button class extending Selectable that disables selecting it with pointers:

public override void OnPointerDown(PointerEventData eventData)
{
    // Temporarily disable navigation to avoid button being selected
    var originalNav = navigation;

    var nav = navigation;
    nav.mode = Navigation.Mode.None;
    navigation = nav;

    base.OnPointerDown(eventData);

    navigation = originalNav;
}

This makes selection exclusive to gamepad/keyboard, which I think is much cleaner anyway.

1 Like

Oh neat, I will try this and report back.

This works wonderfully!

As an FYI i use a different method with the new input system.


    private void OnEnable()
    {
        InputSystem.onEvent += OnAnyButtonPressed;
    }

    private void OnDisable()
    {
        InputSystem.onEvent -= OnAnyButtonPressed;
    }
    private void OnAnyButtonPressed(InputEventPtr eventPtr, InputDevice device)
    {
        if(device is Keyboard or Gamepad)
            UpdateScroll();
    }