The Better Navigation component is crucial for the whole navigation system to work.

It must be added to the same game object that also holds the Event System and Input Module.

You can easily add a Better Navigation component, by right-clicking on the Event System and selecting "Add Better Navigation".

Inspector Properties

Omit Selection State For Pointer Input

The Problem it solves:

In UGUI 2019+ there are five transition states: Normal, Highlight, Pressed, Selected and Disabled.

Highlight is the state when the mouse is hovering over the selectable element, but it can only transition from the Normal state to highlight.

Selected is the state used for gamepad and keyboard input to display which element is currently focused. If the Navigation property of the selectable is not "None", it will also transition to the selected state after clicking or tapping on it. From the Selected state, the selectable cannot transition to hover, so that the last clicked element will not ever show a hover effect until another element becomes selected.


If the property is checked, Better Navigation will automatically deselect the element as soon as mouse or touch input is detected. This allows the element to transition to the highlighted state when the mouse hovers over it.

However, Better UI remembers the last selected element, so that it will select that element (with a transition to the selected state) as soon as gamepad or keyboard input is detected. This also works when you deselect a selectable by clicking somewhere on the screen.


Handle Navigation Input

If checked Better Navigation handles all the navigation logic. This disables "Send Navigation Events" in the Event System.

This is required if you want to use more Better UI navigation features than just "Omit Selection State For Pointer Input".


The logic applied by Better Navigation to handle input should behave the same as UGUI. However, it cannot be guaranteed that it is exactly the same.


Dirty State Detection

Defines the logic how to detect if Navigation Groups or the "Root Selectables" should update their collection of selectables.

  • None
    The collections are never set dirty. Use this, if you are sure that there are no dynamic elements in the UI. Meaning your UI is defined in prefabs or the scene, but nothing is instantiated or destroyed via code.
  • Check Count Change
    The number of currently active selectables are compared to the number of selectables from the previous frame. This is correctly detecting changes for the very most cases and is pretty fast.
  • Check Each Selectable
    This will keep track of all selectables and compares each of them to the selectables of the previous frame. This detects if a selectable was removed and another one was added in the same frame, resulting in the same count of selectables. 
    While the implementation is well optimized, it is still a lot slower than Check Count Change.


Root Selectables

An Selectable Collection which do not belong to any Navigation Group.




Code Access


Static


Current

Returns the Better Navigation instance that is on the same Game Object as EventSystem.current (can return null).


InputDetectorsForInputModulesFactories

This is a dictionary to instantiate the correct Input Detector for the given input system. Better UI supports out of the box Unity's legacy input system, Unity's "new" input system as well as Rewired (if enabled with the wizard).

If you use a different input system, you can support this by adding a new entry to that dictionary:

Key: The type of the Input Module (derived from Unity's "BaseInputModule") for the input system you are using

Value: A Func<BaseInputModule, IInputDetector>. You can assume that the BaseInputModule parameter has the same type as you defined as key. The Func should return your own implementation of a class that implements IInputDetector.


Make sure you add your custom entry before BetterNavigation Awake is called (you may need to set the script execution order of your class to a negative value).


LastSelection

Gets the Selectable that was selected last. It may not have a selected state currently.


SelectableChanged

A Callback that is called whenever the current selectable has changed.

void CurrentSelectableChanged(Selectable previousSelectable, Selectable currentSelectable)

Note that both parameters may be null in certain cases (on deselect / re-select).



SetDirty()

Invalidates the state of all Selectable Collections and recollects all selectables of the current Navigation Group.


Non-Static


EventSystem

The EventSystem component on the same game object.


ElementCollection

Gets the Root Selectables.


HandleNavigationInput

See Inspector Properties


OmitSelectionStateForPointerInput

See Inspector Properties


InputDetector

Gets the Input Detector for the used Input System.


HasCancelAction

Returns true if a cancel action has been triggered at the last update - or if the currently active Navigation Group has a cancel action assigned.

As the cancel action may have destroyed the previously active Navigation Group, it might be interesting to know, if the action was handled this frame, so your game's input logic does not trigger some non-UI logic.


CurrentSelectables

The Selectables which are managed by the current Navigation Group. If there is no Navigation Group active, it returns the Root Selectables (see Inspector Properties).


Notes

Better Navigation derives from Selectable, although it actually is no selectable and cannot be selected (unless you find a way). This is to be able to access static members which are marked protected. They are needed for an efficient dirty-state-detection.