Class InputRebindManager
A UI-agnostic facade that provides all the logic needed to build an input configuration/remapping screen in a game. It sits between the raw Scylla Input module managers and any UI implementation, handling data model building, modifier-aware rebinding, conflict detection, batch operations, and persistence integration.
Implements
Inherited Members
Namespace: Scylla.Input
Assembly: ScyllaInput.dll
Syntax
public class InputRebindManager : IDisposable
Remarks
The manager builds a structured, queryable data model from the registered IInputActionManager organized by configurable ConfigSchemeGroup instances. Each action produces one or more ConfigActionEntry instances (directional composites expand into per-part entries), each containing one ConfigBindingEntry per scheme group.
Typical usage:
var manager = new InputRebindManager(
ScyllaInput.Instance.ActionManager,
ScyllaInput.Instance.BindingManager,
ScyllaInput.Instance.ContextManager
);
manager.Initialize(
new ConfigSchemeGroup("WASD"),
new ConfigSchemeGroup("Gamepad", "<Gamepad>")
);
var entries = manager.GetEntriesForMap("Gameplay");
Constructors
InputRebindManager(IInputActionManager, IInputBindingManager)
Initializes a new InputRebindManager with the specified manager references.
Declaration
public InputRebindManager(IInputActionManager actionManager, IInputBindingManager bindingManager)
Parameters
| Type | Name | Description |
|---|---|---|
| IInputActionManager | actionManager | The action manager providing access to all registered actions and bindings.
Must not be |
| IInputBindingManager | bindingManager | The binding manager providing rebinding, persistence, and conflict detection.
Must not be |
Remarks
The context manager is deliberately not a dependency. Conflict scoping is declared by the game through ConfigLayout rather than inferred from the context stack, because the two answer different questions: a context stack describes what is enabled right now, while a config screen must report what could ever collide across every state the game can reach.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
Fields
DEFAULT_CLEAR_BINDING_PATH
Default Unity Input System control path for the clear binding key.
Declaration
public const string DEFAULT_CLEAR_BINDING_PATH = "<Keyboard>/delete"
Field Value
| Type | Description |
|---|---|
| string |
LABEL_NO_BINDING
Display text used when no binding exists for a scheme group.
Declaration
public const string LABEL_NO_BINDING = "--"
Field Value
| Type | Description |
|---|---|
| string |
Properties
ActionCount
Gets the number of actions counting only the first scheme group's bindings. This represents the number of unique action entries without inflating across multiple control schemes.
Declaration
public int ActionCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
ActionMapCount
Gets the number of action maps in the data model.
Declaration
public int ActionMapCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
BindingCountTotal
Gets the total number of bound binding entries across all entries and all scheme groups (e.g., 4 scheme groups with 60 actions = up to 240 total).
Declaration
public int BindingCountTotal { get; }
Property Value
| Type | Description |
|---|---|
| int |
ClearBindingPath
Gets or sets the Unity Input System control path that clears (unbinds) a binding when pressed during an active rebind session. The key assigned to this path cannot be used as a regular binding.
Declaration
public string ClearBindingPath { get; set; }
Property Value
| Type | Description |
|---|---|
| string | A control path string (e.g., |
ConflictCount
Gets the number of rebindable-binding conflicts currently detected. Only counts conflicts on bindings that can be interactively remapped (excludes non-rebindable bindings like mouse scroll, gamepad sticks).
Declaration
public int ConflictCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
GroupCount
Gets the number of action groups in the data model, including the implicit ungrouped one when some action matched no declared group.
Declaration
public int GroupCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
GroupIDs
Gets the declared action group IDs in declaration order, which is the order a table renders them. Includes UNGROUPED_ID when some action matched no declared group.
Declaration
public IReadOnlyList<string> GroupIDs { get; }
Property Value
| Type | Description |
|---|---|
| IReadOnlyList<string> |
IsInCooldown
Gets a value indicating whether the manager is currently within the post-completion cooldown window during which StartRebind(ConfigBindingEntry) calls are silently rejected.
Declaration
public bool IsInCooldown { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
UI callers should check this before preparing their own mid-rebind visual state (e.g., changing a cell's label to a prompt), otherwise a pointer-up OnClick that fires right after a mouse-button rebind completion would leave the UI stuck.
IsInitialized
Gets a value indicating whether this manager has been initialized.
Declaration
public bool IsInitialized { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsRebinding
Gets a value indicating whether a rebind operation is currently active.
Declaration
public bool IsRebinding { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Layout
Gets the layout this manager was initialized with, or null before initialization.
Declaration
public ConfigLayout Layout { get; }
Property Value
| Type | Description |
|---|---|
| ConfigLayout |
MapIDs
Gets the ordered list of action map IDs discovered from the IInputActionManager.
Declaration
public IReadOnlyList<string> MapIDs { get; }
Property Value
| Type | Description |
|---|---|
| IReadOnlyList<string> |
SchemeGroups
Gets the configured scheme groups that were passed to Initialize(ConfigLayout).
Declaration
public IReadOnlyList<ConfigSchemeGroup> SchemeGroups { get; }
Property Value
| Type | Description |
|---|---|
| IReadOnlyList<ConfigSchemeGroup> |
Methods
AutoResolveConflicts()
Automatically resolves all detected binding conflicts by remapping conflicting bindings to available, unmapped keys. Processes actions in sequential action map order; the first binding to claim a key wins, and later conflicting bindings are remapped.
Declaration
public AutoResolveResult AutoResolveConflicts()
Returns
| Type | Description |
|---|---|
| AutoResolveResult | An AutoResolveResult describing the changes made, how many conflicts were resolved, and how many remain. |
Remarks
Only key/button bindings are considered for remapping. Axes, deltas, sticks, and other non-discrete inputs are skipped. Currently only keyboard keys are supported as replacement candidates.
The key suggestion algorithm tries, in order:
- First letters of significant words in the action name (skipping common verbs).
- Remaining unique letters from the action name.
- All keyboard letters A-Z.
- Number keys 0-9.
- Function keys F1-F12.
If a binding in one scheme group is remapped, other scheme groups for the same action are also remapped only if they have a conflict on the same path.
BuildModifierCompositeDisplay(IReadOnlyList<ScyllaInputBinding>, int)
Convenience wrapper delegating to BuildModifierCompositeDisplay(IReadOnlyList<ScyllaInputBinding>, int).
Declaration
public static string BuildModifierCompositeDisplay(IReadOnlyList<ScyllaInputBinding> bindings, int partListIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyList<ScyllaInputBinding> | bindings | |
| int | partListIndex |
Returns
| Type | Description |
|---|---|
| string |
CancelRebind()
Cancels the currently active rebind operation, if any. Publishes a ManagedRebindCancelledEvent.
Declaration
public void CancelRebind()
ClearAll()
Clears all binding overrides by setting each rebindable binding to an empty path. Refreshes the data model after clearing.
Declaration
public void ClearAll()
Dispose()
Releases all resources held by this manager and clears the data model.
Declaration
public void Dispose()
FormatPartName(string)
Convenience wrapper delegating to FormatPartName(string).
Declaration
public static string FormatPartName(string partName)
Parameters
| Type | Name | Description |
|---|---|---|
| string | partName |
Returns
| Type | Description |
|---|---|
| string |
GetAllConflicts()
Returns all conflicts detected across all actions in the data model.
Declaration
public IReadOnlyList<ConfigConflict> GetAllConflicts()
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigConflict> | A read-only list of ConfigConflict instances. |
GetAllEntries()
Returns all action entries across all maps, in the order they were discovered.
Declaration
public IReadOnlyList<ConfigActionEntry> GetAllEntries()
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigActionEntry> |
GetConflictsForAction(string, string)
Returns all conflicts detected for the specified action across all its binding entries and scheme groups.
Declaration
public IReadOnlyList<ConfigConflict> GetConflictsForAction(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | |
| string | actionID | The action ID to check for conflicts. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigConflict> | A read-only list of ConfigConflict instances, one per detected conflict. Returns an empty list if no conflicts are found. |
GetConflictsForBinding(string, string, int, string, string)
Returns all conflicts for a specific binding in a specific scheme group. Use this for per-row conflict detection in directional composites where multiple rows share the same action ID but have different binding indices.
Declaration
public IReadOnlyList<ConfigConflict> GetConflictsForBinding(string mapID, string actionID, int bindingIndex, string schemeGroup, string effectivePath)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map declaring the action. |
| string | actionID | The action's name within that map. |
| int | bindingIndex | The flat Unity binding index to check. |
| string | schemeGroup | The scheme group to scope the conflict check. |
| string | effectivePath | The effective control path to check for conflicts. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigConflict> | A read-only list of ConfigConflict instances for this specific binding. |
GetConflictsForEntry(ConfigActionEntry)
Returns every conflict on one row, across every column, which is what a table's Conflict cell reports.
Declaration
public IReadOnlyList<ConfigConflict> GetConflictsForEntry(ConfigActionEntry entry)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigActionEntry | entry | The row to check. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigConflict> | A freshly allocated, deduplicated list of conflicts affecting this row. Safe to cache. |
Remarks
A row is one action or one directional-composite part, and it holds one binding per column. Asking per row rather than per cell is what the Conflict column wants, and it saves every caller from writing the same loop over Bindings.
GetEntriesForAction(string, string)
Returns all action entries for the specified action ID. For simple actions this returns a single entry. For directional composites this returns one entry per composite part (e.g., Up, Down, Left, Right).
Declaration
public IReadOnlyList<ConfigActionEntry> GetEntriesForAction(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map declaring the action. |
| string | actionID | The action's name within that map. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigActionEntry> | A read-only list of entries, or an empty list if the action is not found. |
GetEntriesForGroup(string)
Returns all action entries belonging to the specified config group, which is how a table renders itself: one heading, then that heading's rows.
Declaration
public IReadOnlyList<ConfigActionEntry> GetEntriesForGroup(string groupID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupID | The group ID to query. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigActionEntry> | A read-only list of entries for the group, or an empty list if the group ID is unknown. |
GetEntriesForMap(string)
Returns all action entries belonging to the specified action map.
Declaration
public IReadOnlyList<ConfigActionEntry> GetEntriesForMap(string mapID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map ID to query. |
Returns
| Type | Description |
|---|---|
| IReadOnlyList<ConfigActionEntry> | A read-only list of entries for the map, or an empty list if the map ID is not found. |
GetGroupDisplayName(string)
Returns the heading to show above a group's rows.
Declaration
public string GetGroupDisplayName(string groupID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | groupID | The group ID to query. |
Returns
| Type | Description |
|---|---|
| string | The declared display name, or the group ID itself when unknown. |
GetRebindability(string, string)
Returns how the named action may be rebound.
Declaration
public InputRebindability GetRebindability(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map's name. |
| string | actionID | The action's name within that map. |
Returns
| Type | Description |
|---|---|
| InputRebindability | The action's rebindability. |
Remarks
Exposed so a config screen can style a cell without reaching for the metadata sidecar itself. Every action is Rebindable when the manager was initialized without a provider.
HasConflicts(ConfigActionEntry)
Returns whether the action a row belongs to has any binding conflicts.
Declaration
public bool HasConflicts(ConfigActionEntry entry)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigActionEntry | entry | The row whose action to check. |
Returns
| Type | Description |
|---|---|
| bool |
|
HasConflicts(string, string)
Returns whether the specified action has any binding conflicts.
Declaration
public bool HasConflicts(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map declaring the action. |
| string | actionID | The action's name within that map. |
Returns
| Type | Description |
|---|---|
| bool |
|
Initialize(ConfigLayout)
Initializes the manager with the specified scheme groups and builds the data model from the registered action maps.
Declaration
public void Initialize(ConfigLayout layout)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigLayout | layout | The table description: columns, action groups, and exclusive sets. The column order determines the order of Bindings, and the group order determines the order of GroupIDs. |
Remarks
Only bindings that belong to one of the supplied schemeGroups
(or that are scheme-less - i.e. have an empty Groups string, such as
Console/Global actions) are processed. Bindings tagged with a scheme the caller
did not register are silently ignored across all manager operations: they are
not displayed in the data model, not considered for conflict detection, not
included in occupiedPaths during auto-resolve, and are left untouched
inside the input actions asset.
A caller that registers only "WASD" therefore gets a single-column
binding table; registering "WASD" and "Gamepad" produces a
two-column table and scopes all processing to those two schemes.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
| ArgumentException | Thrown when an action belongs to more than one group, or an exclusive set names a group that was never declared. Both make the conflict column meaningless, so they fail here rather than producing a table nobody can trust. |
Initialize(ConfigLayout, IInputRebindabilityProvider, bool)
Initializes the manager against a layout, honouring per-action rebindability.
Declaration
public void Initialize(ConfigLayout layout, IInputRebindabilityProvider rebindability, bool schemesAreExclusive = false)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigLayout | layout | The layout describing columns, groups and exclusions. |
| IInputRebindabilityProvider | rebindability | Supplies per-action rebindability, or |
| bool | schemesAreExclusive | Whether two bindings that share no control scheme are exempt from conflicting, which is
what an asset's |
Remarks
An action the provider reports as Hidden is left out of the table entirely, and one reported Protected gets a row that displays its bindings but refuses to rebind them. Passing no provider treats every action as rebindable, which is what the manager did before this existed.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when the layout is |
| ArgumentException | Thrown when an action belongs to more than one group, or an exclusive set names a group that was never declared. |
IsBindingRebindable(ScyllaInputBinding)
Convenience wrapper delegating to IsBindingRebindable(ScyllaInputBinding).
Declaration
public static bool IsBindingRebindable(ScyllaInputBinding binding)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaInputBinding | binding |
Returns
| Type | Description |
|---|---|
| bool |
IsInModifierComposite(IReadOnlyList<ScyllaInputBinding>, int)
Convenience wrapper delegating to IsInModifierComposite(IReadOnlyList<ScyllaInputBinding>, int).
Declaration
public static bool IsInModifierComposite(IReadOnlyList<ScyllaInputBinding> bindings, int listIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyList<ScyllaInputBinding> | bindings | |
| int | listIndex |
Returns
| Type | Description |
|---|---|
| bool |
IsRebindable(string, string)
Returns whether the player may rebind the named action.
Declaration
public bool IsRebindable(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | The action map's name. |
| string | actionID | The action's name within that map. |
Returns
| Type | Description |
|---|---|
| bool |
|
LoadBindings(string)
Loads binding overrides from the configured IBindingStorage and refreshes the data model.
Declaration
public void LoadBindings(string profileID = null)
Parameters
| Type | Name | Description |
|---|---|---|
| string | profileID | Optional profile ID. Pass |
RefreshAction(ConfigActionEntry)
Refreshes the cached binding cells of the action a row belongs to.
Declaration
public void RefreshAction(ConfigActionEntry entry)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigActionEntry | entry | The row whose action to refresh. |
RefreshAction(string, string)
Refreshes the binding entries for a specific action, updating display text, effective paths, and override status without rebuilding the entire model.
Declaration
public void RefreshAction(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | |
| string | actionID | The action ID whose entries should be refreshed. |
Remarks
The action's own binding cache is refreshed first, so this reports the paths that are in force rather than the ones that were in force when the action was last read. Bindings is a cached list that only RefreshBindings() rebuilds, so without this the method would read whatever the cache held and quietly return the pre-rebind display strings.
This matters for any caller reacting to
IInputBindingManager.OnRebindCompleted, which is raised by the low-level
binding manager before this manager has synchronized its own model. The whole-model
path has always done this through RefreshAllActionBindings; the single-action
path did not, which made a refreshed action show its previous binding until
something else happened to refresh it.
RefreshAll()
Rebuilds the entire data model from the current state of the action manager. Call this after loading bindings or resetting to defaults to refresh all entries.
Declaration
public void RefreshAll()
ResetAction(ConfigActionEntry)
Resets every binding of the action a row belongs to back to the asset defaults.
Declaration
public void ResetAction(ConfigActionEntry entry)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigActionEntry | entry | The row whose action to reset. |
ResetAction(string, string)
Resets bindings for a specific action to their default values and refreshes that action's entries.
Declaration
public void ResetAction(string mapID, string actionID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | |
| string | actionID | The action ID to reset. |
ResetAll()
Resets all bindings to their default values and refreshes the data model.
Declaration
public void ResetAll()
SaveBindings(string)
Saves the current binding overrides via the configured IBindingStorage.
Declaration
public void SaveBindings(string profileID = null)
Parameters
| Type | Name | Description |
|---|---|---|
| string | profileID | Optional profile ID. Pass |
StartRebind(ConfigBindingEntry)
Starts an interactive rebind for the specified action and binding. Automatically selects the rebinding mode based on the binding's device type: keyboard bindings use modifier-aware polling (supports Shift+A combos), while gamepad and mouse bindings use Unity's native interactive rebinding. Publishes a ManagedRebindStartedEvent on start.
Declaration
public bool StartRebind(ConfigBindingEntry binding)
Parameters
| Type | Name | Description |
|---|---|---|
| ConfigBindingEntry | binding | The cell to rebind. |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
Callers must act on the result. Several conditions reject a start, and the cooldown one is silent by design because it exists to swallow the click that just completed a rebind. A caller that assumes the capture began, and switches its UI into a listening state on that assumption, waits forever for a completion event that is never coming. Where that listening state also disables input, as a screen pushing a rebinding context does, the result is an unrecoverable lock-up.
The safe shape is to call this first and only commit to the listening state when
it returns true.
StartRebind(string, string, int, string)
Declaration
public bool StartRebind(string mapID, string actionID, int bindingIndex, string schemeGroup)
Parameters
| Type | Name | Description |
|---|---|---|
| string | mapID | |
| string | actionID | |
| int | bindingIndex | |
| string | schemeGroup |
Returns
| Type | Description |
|---|---|
| bool |