Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion Thoughts on the UI Toolkit focusing algorithm. Can we change it?

Discussion in 'UI Toolkit' started by _geo__, Aug 16, 2023.

  1. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,111
    I was struggling a bit to understand how the focusing alogrithm works. I does not yield very good results (at least in my tests).

    Let's assume this situation:
    FocusingBehaviour1.png
    I wondered why the algorithm was unable to focus the other button. So I dove into the UI source code and found this:
    Code (csharp):
    1.  
    2. Rect panelBounds = m_Root.worldBoundingBox;
    3. Rect panelRect = new Rect(panelBounds.position - Vector2.one, panelBounds.size + Vector2.one * 2);
    4. Rect rect = ve.worldBound;
    5. Rect validRect = new Rect(rect.position - Vector2.one, rect.size + Vector2.one * 2);
    6. if (direction == Up) validRect.yMin = panelRect.yMin;
    7. else if (direction == Down) validRect.yMax = panelRect.yMax;
    8. else if (direction == Left) validRect.xMin = panelRect.xMin;
    9. else if (direction == Right) validRect.xMax = panelRect.xMax;
    10.  
    Here is what that code does:
    FocusingBehaviour2.png

    If you want to make a game ui that supports gamepad and keyboard input this is bad news. Users may get stuck if there is no overlapping focusable element in one of the four directions.

    Another issue I have with the algorithm is that is uses only the children inside the "contentContainer".
    Usually that is fine but there are some Unity Controls (like the ScrollView) that put elements outside the contentContainer (they override the contentContainer) and thus effectively make their controls inaccessible via keyboard or gamepad. You can focus them with the mouse or TAB but that is hard to explain to console players ;-)

    I don't think that contentContainer overrides were an accident. I think that's by design. Though, I do not like the focusing side-effects it has.

    Does anyone know if we can inject a custom focus traversal method?
     
    Last edited: Aug 16, 2023
    oscarAbraham likes this.
  2. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    732
    I believe this is due to the fact that directional arrows are by default trying to navigate the focus purely based on the spatial position of the visual elements.

    The other way of moving the focus is through tabbing which is based on the tree ordering (although that can be reconfigured with tab indices).

    Unfortunately there is no way to override the tab or shift+tab combination to move the focus currently.

    So I believe you would have to resort to intercepting the NavigationMoveEvent at the rootVisualElement and prevent it from doing the focus change by calling StopPropagation().
     
  3. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,111
    Sadly tabbing is not a good option for console players. AFAIK there is no default button assigned to "tab" on a controller (tried on xbox).

    Thanks. I was hoping for another solution. What I do now is intercept at the Control root level and do my own focusable discovery (or rather I make elements temporarily focusable to trigger the behaviour I want).
     
    Last edited: Aug 17, 2023