UI Navigation needs improvements, more freedoom etc (gamepad problem)

Hello, I’d like to share an experience as an advanced UI developer in Unity and highlight a problem I encountered when we start to use gamepad.

Summary (Short Version):

  • Issue:
    No built-in mechanism to filter Selectable elements when navigating with a gamepad in Unity’s UI (Navigation).
  • Limitations:
    FindSelectable(dir) cannot be modified. So you cannot add your own logic for the condition what should be selected next.
  • Requested feature:
    Add an interface (e.g., IFindSelectableCondition) to FindSelectable that allows developers to define custom selection logic.: if (!sel.IsInteractable() || sel.navigation.mode == Navigation.Mode.None || !IFindSelectableCondition.CanBeSelected)

Long Story
We have a really complex UI in Unity, and we’re not using it for games.

When we started implementing gamepad support, we ran into serious issues. It took much more time and effort than we anticipated, to the point where we almost lost hope.

Let me explain.

When navigating the UI via gamepad, how can we filter selectables? There is no filtering mechanism.

The Selectable class has a FindSelectable(dir) function, but you cannot modify it. There’s also the “Navigate” function, which is also non-overridable.

It would be great if FindSelectable could check for interfaces with custom logic, so that we could override certain functions.

There is also no precheck functions. Like “I will move right”, but return false… so “you cannot move there… try next one” etc. Return true to allow to select right element (like button, toggle etc).

Yes, I know what you might say: “You can create custom buttons and elements to implement your own logic.” Sure, but why reinvent the entire system? Should I rewrite the entire EventSystem and its modules too? Maybe even the whole UI system?

When I saw the interfaces like ISelectHandler etc I hoped it can modify the FindSelectable like it could have return value to tell FindSelectable “please use my condition… not yours.”… but sadly I didn’t find.

Why is a filter mechanism necessary?

It would allow us to implement custom conditions. Imagine you have a popup, but everything in the background is still interactable. A filter could ensure that only elements within the popup are selectable, by applying conditions like “the next element should have the same Z-position, belong to the same group, or have the same parent,” etc. This would prevent focus from leaving the popup.
Something like “s is Popup children? Then you can be selected”. MUCH easer than to make whole managment system, canvasgroup.interactables etc. Because with mouse you still want to click other buttons… but not with gamepad.

I’m requesting an interface be added to the line in FindSelectable:

mathematica

Code kopieren

if (!sel.IsInteractable() || sel.navigation.mode == Navigation.Mode.None || !IFindSelectableCondition.CanBeSelected) 

Something like IFindSelectableCondition, so we can define the conditions for how the next selection should be made.

Currently, to solve this, we have to use a bunch of loops, tracking all selectables with lists and dictionaries essentially creating an extension for something that could be solved with just one interface.

The easiest solution would be to copy the entire UI folder and modify the scripts ourselves, but we want to continue receiving updates, so modifying them isn’t ideal.

Yeah, FindSelectable to a virtual method might help for special cases. My solution so far has been subclassing UI Button and other classes, and overriding what’s possible, which is FindSelectableOnDown, FindSelectableOnUp, etc. Then I can choose to call FindSelectable(dir) itself or do something special.