Configure input bindings¶
This page covers two procedures. Setting bindings at construction
through Configuration.Bindings, and replacing them at runtime
through UI.SetBindings. Both work on the same InputBindings
container and the same per-feature bindings classes.
For the model behind the bindings framework, refer to Input bindings.
To customise bindings at setup¶
- Build an
InputBindingsvalue with the fields you want to change. Leave the other fields null; defaults fill them at ingest:var bindings = new InputBindings { Navigation = new LegacyNavigationBindings { Up = { KeyCode.W, KeyCode.UpArrow }, Down = { KeyCode.S, KeyCode.DownArrow }, Left = { KeyCode.A, KeyCode.LeftArrow }, Right = { KeyCode.D, KeyCode.RightArrow }, ConfirmKeys = { KeyCode.Return, KeyCode.Space, KeyCode.JoystickButton0 }, CancelKeys = { KeyCode.Escape, KeyCode.JoystickButton1 }, }, }; - Assign the value to
Configuration.Bindingsbefore constructing theUI.
The constructor copies the bindings into UI.Bindings. Null
fields become per-feature defaults (NavigationBindings.Default,
TextboxBindings.Default, and so on). Widgets read the customised
bindings from the first frame.
To replace bindings at runtime¶
Build a new InputBindings value the same way, then pass it to
UI.SetBindings:
var textbox = LegacyTextboxBindings.Default as LegacyTextboxBindings;
textbox.SubmitBindings = new List<LegacyKeyBinding>
{
new LegacyKeyBinding(KeyCode.KeypadEnter),
new LegacyKeyBinding(KeyCode.Return),
};
ui.SetBindings(new InputBindings
{
Textbox = textbox,
});
Null fields are filled with defaults again. SetBindings is safe
to call between frames. Widgets pick up the new bindings on the
next frame.
To bind a controller D-pad on the legacy backend¶
Legacy Input has no built-in D-pad button.
LegacyNavigationBindings reads two Input Manager axes and
computes the press events itself:
- Add two axes under Project Settings > Input Manager
mapped to the controller D-pad.
The default axis names are
DPadHorizontalandDPadVertical. Set Type to Joystick Axis for each axis, and pick the correct joystick axis index for the target controller. - Confirm
UseDpadistrueon the legacy navigation bindings. It istrueby default. Set it tofalseto disable D-pad navigation entirely. - Optionally rename the axes.
Set
DpadHorizontalAxisandDpadVerticalAxisonLegacyNavigationBindingsto match the names used in the Input Manager.
On the Input System backend, the D-pad is read directly through
Gamepad.current.dpad. No project configuration is required.
To add a shortcut with a modifier¶
LegacyKeyBinding and InputSystemKeyBinding both take a
ModifierMask argument. The match is exact: a binding with
Ctrl only fires when no other modifier is held.
var textbox = LegacyTextboxBindings.Default as LegacyTextboxBindings;
textbox.SelectAllBindings = new List<LegacyKeyBinding>
{
new LegacyKeyBinding(KeyCode.A, ModifierMask.Ctrl),
};
textbox.CopyBindings = new List<LegacyKeyBinding>
{
new LegacyKeyBinding(KeyCode.C, ModifierMask.Ctrl),
};
To accept multiple modifier combinations for the same action, list each binding separately:
textbox.CopyBindings = new List<LegacyKeyBinding>
{
new LegacyKeyBinding(KeyCode.C, ModifierMask.Ctrl),
new LegacyKeyBinding(KeyCode.C, ModifierMask.Ctrl | ModifierMask.Shift),
};
To add a gamepad button on the Input System backend¶
InputSystemKeyBinding accepts an InputSystemControl, which
implicitly converts from Key and from GamepadButton. Pass a
GamepadButton directly:
var nav = new InputSystemNavigationBindings
{
Up = { Key.UpArrow, GamepadButton.DpadUp },
Down = { Key.DownArrow, GamepadButton.DpadDown },
Left = { Key.LeftArrow, GamepadButton.DpadLeft },
Right = { Key.RightArrow, GamepadButton.DpadRight },
ConfirmControls = { Key.Enter, GamepadButton.South },
CancelControls = { Key.Escape, GamepadButton.East },
};
GamepadButton.LeftShoulder, GamepadButton.RightShoulder,
GamepadButton.Start, and the other Input System gamepad
buttons work the same way.
Pitfalls¶
A custom binding for one action erases all the others.
: new LegacyTextboxBindings() creates an instance with empty
Lists for every action. Setting only one field leaves the
others empty, not defaulted. To replace a single action while
keeping the rest of the defaults, start from
LegacyTextboxBindings.Default, mutate the field you want to
change, and assign the result:
var tb = LegacyTextboxBindings.Default as LegacyTextboxBindings;
tb.CopyBindings = new List<LegacyKeyBinding> { ... };
bindings.Textbox = tb;
A modifier shortcut fires for the wrong combination. : Modifier match is exact. Add a separate binding entry for each combination you want to accept.
A runtime SetBindings does not affect this frame.
: Bindings are read by widgets when each widget runs.
SetBindings mid-frame affects later widgets in the same
DoUI body but not earlier ones. To swap bindings cleanly,
call SetBindings between frames.
The legacy D-pad still does nothing after adding the axes.
: The axis names on LegacyNavigationBindings and the names in
the Input Manager must match exactly. Verify both, including
capitalisation.
Additional resources¶
- Input bindings: the model that lists every action and how the polymorphic split works.
- Navigation: the consumer of
NavigationBindings. - Build a navigable menu: the procedure that reads the bindings configured here.
- Configuration: the configuration struct that holds bindings.