The Input Actions editor: editing .inputactions assets in place, the metadata sidecar that carries notes and layout, live conflict detection, constants generation, and moving a setup between projects.
Summary
The Input Actions editor is Scylla’s own window for .inputactions assets, opened from
Tools/Scylla/Input/Input Actions Editor.... It edits the stock Unity file in place, so an asset
authored here still works with PlayerInput and Unity’s generated wrapper, and an asset authored in
Unity’s own editor opens here unchanged. Nothing is converted and nothing is locked in.
Alongside the asset it keeps a sidecar, MyGame.scyllainput.asset, holding everything the
.inputactions format has no room for: authoring notes, display name overrides, which actions are
protected from rebinding, which icon set supplies a scheme’s glyphs, and the layout a controls screen
renders from. The sidecar is keyed by the action asset’s GUID rather than by its file name, so
renaming or moving either file keeps the two attached, and a rename made in Unity’s editor keeps every
annotation on the element it describes.
The window is a tree of maps, actions and bindings beside nine panels. Most of the time two of them matter: Bindings, which edits whatever is selected, and Matrix, which lays every action against every binding group and highlights the cells where two actions would fire from one key. The rest cover the asset itself, control schemes, contexts, the config layout, validation, glyphs, and code generation. The Concepts section of the Input overview explains what each of these terms means, including the difference between a control scheme and a binding group.
Starting a New Asset
The tabs run left to right in the order an asset is usually built, so working through them in sequence is a reasonable default. What follows is that same order with the reasons attached, since two of the steps are worth doing before it is obvious why.
- Create the asset, from the toolbar or from
Assets > Create > Input Actions. The setup wizard’s Game Profile step is the other way in: it copies a factory asset written for the genre into the project, with its sidecar and a context configuration naming that asset’s maps, and applies the buffering and scheme-detection values that suit the genre while it is there. It covers twelve genres, from 3D Action through Fighting to Flight Sim. Configuration says what each asset holds. - Create the metadata sidecar, from the banner at the top of the window. It is not created for you. Until it exists there is nowhere to record descriptions, the context configuration, the config layout, glyph assignments or codegen settings, and those parts of the window stay disabled.
- Add the control schemes, on the Schemes tab, before writing any bindings. A binding belongs to a scheme through that scheme’s binding group, so bindings written first apply under every scheme and have to be assigned one by one afterwards. Having the schemes first also gives the Matrix its columns while there is still something to see in them.
- Add the action maps, actions and bindings.
- Set up the contexts, on the Contexts tab, once the maps exist. Reference the project’s context configuration or create one, say which maps each context enables, and give a shared conflict-exclusive tag to the contexts that can never be live at the same time.
- Finish with the layout, the glyphs and the generated constants. The layout can take its exclusive sets from the contexts, glyphs are assigned per scheme, and the generated constants cover everything above.
Step 5 is the one that reads out of order and is not. A context names its action maps by name, and the picker only offers maps the open asset actually has, so a context written before its maps either cannot be filled in or ends up naming maps that do not exist. The Coverage grid flags those, but it is easier not to create them.
A context configuration is shared across action assets rather than owned by one, so for a second
asset step 5 is usually just pointing at the configuration that already exists. And if the project
itself is new, the setup wizard handles the part this window does not: creating that configuration
and assigning it to the ScyllaInput component.
Use the editor for:
- Editing maps, actions, bindings and composites, with undo that belongs to the window rather than to Unity’s global stack.
- Seeing binding conflicts as you author, rather than discovering them from a bug report.
- Recording why a binding is the way it is, and marking the ones a player must not rebind.
- Authoring the controls-screen layout instead of writing it in code.
- Generating constants so a renamed action breaks the build rather than the game.
- Moving an action asset and everything attached to it into another project.
Picking a Control
A binding’s path has two ways in besides the text field: a searchable picker, and a Listen button that binds whatever you press.
The … button beside the path field opens the picker, a list of every control path the project
can bind, each row carrying the path with its device and control type beneath it. Ranking favors an
exact control name, then a prefix, then initials, so lsx finds leftStick/x. The list arrives
filtered to what the binding can actually use: the action’s expected control type, and the devices
the binding’s control schemes require. When the filter is hiding entries, the footer says how many
and offers to drop it, which matters because an action with a misspelled expected control type
otherwise looks exactly like a broken picker. Double-clicking a bound cell in the Matrix opens the
same picker, filtered from that cell’s row and column instead.
Listen binds the next control pressed, in Edit mode, with no round trip through Play mode. Its tooltip names the devices it can currently hear, since whether a pad reaches the editor at all depends on the project’s background behavior and on the device having been enumerated. Escape cancels, and a session that hears nothing gives up after five seconds. The button is disabled while the game is playing, since a capture running then would swallow the first press the player makes.
A modifier is not part of a control path, so a captured combination becomes a composite. Press Shift
and A together and the binding turns into a Button With One Modifier rather than a bare
<Keyboard>/a, which names the same control whether or not Shift was down. Inside a composite that
conversion has nowhere to go, because the Input System does not nest composites, so capturing a
combination onto a composite part binds the control alone and reports the modifier it had to drop.
Conflicts
Two actions bound to the same key are only a problem when both can fire at once, and the matrix knows
the difference. It reads the project’s input contexts: if every context that enables one action’s map
also excludes the other’s, the two can never be live together and the shared key is not a conflict.
Movement in a gameplay context and camera panning in a free-camera context can both sit on W without
complaint, because the contexts that enable them are declared mutually exclusive.
Where nothing declares exclusivity, the matrix assumes action maps are mutually exclusive and says so, rather than either flooding the panel with false conflicts or staying quiet about real ones.
Device class matters too. A keyboard binding and a gamepad binding never conflict, because no player
has both hands on the same physical control. Aliases are resolved before comparison, so
<Gamepad>/buttonSouth and <Gamepad>/a are recognized as one control rather than two.
Interactions count as well, within limits. Crouch on a tap of Left Ctrl and Prone on a one-second hold of the same key are not a conflict: by the time the hold fires, the tap has already canceled itself. The exemption is deliberately narrow, covering a tap against a hold or a slow tap and nothing else. A hold and a slow tap on one key do collide, because a long press and release performs both, and so do a tap and a multi-tap, because a double tap performs both.
A grid that showed only paths would render those two bindings as identical, so the cells carry a badge for what else is going on. Hold gets a mark of its own, a clockwise arrow, since it is the one qualifier that changes how a control feels rather than only what it reports. Everything else that changes a binding without changing its path, such as another interaction or a processor, shares a single footnote mark whose tooltip names what applies. A cell holding several bindings that disagree draws its badge dimmed.
Control schemes are the one case the editor has to be told about. If a game applies a scheme as a binding mask, three keyboard layouts can each use Right Shift for something different and only one of them is ever live. If it enables its action maps without masking, all three are live and the key really is overbooked. Both are reasonable ways to build a game and the asset looks identical either way, so the Schemes tab carries a “Schemes are conflict-exclusive” setting. It is off by default, and the conflict panel points at it when it would clear what is being reported. A binding that names no scheme is unaffected: a mask lets those through, so they stay live in every layout.
The Config Layout
A controls screen needs three declarations: which binding groups become columns, which actions are
grouped under which heading, and which groups are never live together. The Layout panel authors all
three into the sidecar, so ScyllaInputConfigScreenDemo and anything like it can read a layout at run
time instead of having one compiled into it.
Exclusivity can be derived rather than restated. A layout that opts into deriving from contexts picks up the same conflict-exclusive tags the contexts already declare, which keeps the answer to “can these two ever both fire” in one place.
An asset with no authored layout still gets one: the panel derives a column per control scheme and a group per action map, and says that is what it is doing. The matrix falls back to that same derived shape as well, so the two never disagree.
Glyphs
A controls screen shows a button image where a raw control path would otherwise sit, so the player
reads a gamepad face button rather than the word buttonSouth. Those images live in icon sets, and
Control Schemes and Hints covers how the hints system resolves one at
run time. The Glyphs panel handles the authoring side: which icon set answers for each control
scheme, and whether that set has an image for every control the asset binds.
The second question is the one nothing else answers. A missing mapping is silent, because the hints
system falls back to the raw control path, so a shipped game renders buttonSouth where a glyph
belonged and nothing anywhere said so. Select a scheme and the panel lists every distinct path its bindings use,
how many bindings use each, and what the icon set has for it: an image, fallback text, or nothing.
A mapping carrying neither image nor text is called out separately from a missing one, since the
lookup succeeds and returns nothing, which renders a blank hint instead of falling back. Uncovered
paths get an Add Mapping button that writes an empty row into the icon set for an artist to fill
in.
The check runs in the other direction too. The panel reads the icon set’s own keys against Unity’s layout database and reports the ones no binding can ever reach: a device layout that does not exist, a path no device in that family has, and a key that is not a control path at all.
Undo splits here. Assigning an icon set to a scheme is sidecar data and goes on the window’s own undo stack, while adding a mapping writes the icon set asset itself, so that one undoes with Ctrl+Z.
Generated Constants
Scylla’s input API is keyed by string throughout, and a mistyped action name fails silently at run time. The Codegen panel writes a C# file of constants for the asset’s maps, actions, binding groups, control schemes, layout groups, contexts and exclusivity tags:
/* Before: a typo no compiler catches. */
var move = ScyllaInput.Instance.ActionManager.GetActionVector2("On Foot", "Foot Move");
/* After: a renamed map or action breaks the build. */
var move = ScyllaInput.Instance.ActionManager.GetActionVector2(
GameIDs.Maps.OnFoot, GameIDs.Actions.OnFoot.FootMove);
The same file carries a CreateConfigLayout() factory that rebuilds the authored layout in code, so a
controls screen can use a compiled layout with no asset lookup at all.
Names are sanitized into legal identifiers, so Keyboard&Mouse becomes KeyboardMouse and 2D Vector
becomes _2DVector. Two maps sharing a name produce two distinct constants rather than a file that
does not compile. Regenerating an unchanged asset writes nothing, which matters because writing a C#
file makes Unity compile and reload the domain; generate-on-save is off by default for that reason.
Bundles
An action asset and its sidecar are linked by an asset GUID, and a GUID means nothing outside the project that created it. Copying both files into another project produces a sidecar claiming a GUID nothing has, which silently detaches every annotation, the layout and the glyph assignments.
Tools/Scylla/Input/Export Bundle... packages both into one .scyllainputbundle file, and
Import Bundle... writes it back somewhere else, reproducing the action asset byte for byte. Import
previews what the bundle holds and lets you pick which parts land:
- Annotations and protection: notes, display name overrides, categories, tags, and which elements are protected from rebinding.
- Config layout: the columns, groups and exclusivity sets.
- Glyph assignments: per-binding glyph overrides and per-scheme icon sets.
- Codegen settings: the namespace and type name, with the output path cleared and generate-on-save switched off, since both described the project the bundle came from.
- Context link: relinked when the target project has the same context configuration, and left empty with a note when it does not.
Nothing in the target project is overwritten. A name collision produces a new name and says so.
The bundle is plain JSON, so it reviews in a diff like any other file in the repository.
Validation
The Validation panel collects findings from six sources: the document itself, Unity’s own reader, the conflict engine, the metadata sidecar, the layout, and the contexts. The severities mean something specific. An error means the asset will not load, or something in it can never fire. A warning means it runs but is probably not what was meant, such as a binding group no control scheme declares, which is filtered out the moment a scheme becomes active.
Some findings carry a one-click fix. Only the ones where the fix cannot be wrong do: deleting a binding with an empty path, or removing a group token nothing declares. A fix that had to guess is left to the author.
Notes
The window keeps its own undo stack, separate from Unity’s, driven by the toolbar Undo and Redo
buttons rather than by the usual keyboard shortcuts. The tree carries shortcuts that the ? toolbar
button lists in full: Alt with an arrow key reorders and steps over a whole composite rather than
into it, the platform’s action modifier with C, V or D copies, pastes or duplicates, and
Delete removes.
Opening action assets in this editor on a double-click is a per-user preference, off by default, so
double-clicking an .inputactions asset opens Unity’s own editor until you turn it on. See
Preferences.
Related
- 01 Scylla Input
- 03 Input – Actions and Bindings
- 04 Input – Contexts
- 06 Input – Rebinding
- 09 Input – Configuration
- 07 Input – Control Schemes and Hints
- API reference:
Scylla.Input.InputIconSet - API reference:
Scylla.Input.ScyllaInputActionsMetadata - API reference:
Scylla.Input.ConfigLayoutDefinition - API reference:
Scylla.Input.InputActionsDocument - API reference:
Scylla.Input.ConfigLayout