Game.Input.InputConflictResolution
Assembly:
Namespace: Game.Input
Type: class
Base: System.IDisposable
Summary:
Manages and resolves input conflicts between different groups of ProxyAction instances (system actions, UI actions and mod actions). It listens to InputManager events, rebuilds categorized action lists when actions change, and computes which actions conflict based on each action's pre-resolved enable flag and mask. Conflicted actions are marked and then applied back to the ProxyAction instances by calling ProxyAction.ApplyState(enabled, preResolvedMask). The class is intended to be run in a regular update loop (call Update()) and raises events when actions are refreshed or conflicts resolved. It prevents re-entrant updates with an m_UpdateInProgress guard. It depends on the InputManager singleton and on ProxyAction members such as isBuiltIn, isSystemAction, preResolvedEnable and preResolvedMask.
Fields
-
private bool m_ActionsDirty
Tracks that the cached action lists need to be rebuilt (set when InputManager reports actions changed). -
private bool m_ConflictsDirty
Tracks that conflict resolution needs to be run (set when control scheme or pre-resolved action flags change or when actions change). -
private bool m_UpdateInProgress
Guard used to avoid responding to events while an Update() is running (prevents scheduling work mid-update). -
private List<State> m_SystemActions
Cached list of system action State wrappers (ProxyAction instances that are built-in and marked as system actions). -
private List<State> m_UIActions
Cached list of UI action State wrappers (built-in but not system actions). -
private List<State> m_ModActions
Cached list of mod action State wrappers (actions that are not built-in). -
public event Action EventActionRefreshed
Raised after RefreshActions() has rebuilt the action lists during Update(). -
public event Action EventConflictResolved
Raised after ResolveConflicts() has finished during Update(). -
private class State
Inner helper class that wraps a ProxyAction and stores transient state used during conflict resolution: public readonly ProxyAction m_Action
— the wrapped action.public bool m_HasConflict
— flag set when the action is considered in conflict with a higher priority action.public bool enabled { get; }
— computed property: returns true when the wrapped action's preResolvedEnable is true and it currently has no conflict.public State(ProxyAction action)
— constructs and calls Reset().public void Reset()
— clears m_HasConflict.public void Apply()
— calls m_Action.ApplyState(enabled, m_Action.preResolvedMask) to apply the resolved state back to the ProxyAction.
Properties
public bool State.enabled { get; }
(Inside the private State class) Returns true when the associated ProxyAction's preResolvedEnable flag is true and the State is not marked as having a conflict. Used to decide whether the action should be enabled when applying results.
Constructors
-
public InputConflictResolution()
No explicit constructor is defined in source; the default parameterless constructor is available. The instance must be initialized by calling Initialize() before use (to hook InputManager events). -
public State(ProxyAction action)
Constructs a new State wrapper for the given ProxyAction and resets its transient flags.
Methods
public void Initialize()
Subscribes to InputManager events:- InputManager.instance.EventActionsChanged += OnActionsChanged
- InputManager.instance.EventPreResolvedActionChanged += OnPreResolvedActionChanged
-
InputManager.instance.EventControlSchemeChanged += OnControlSchemeChanged
Call this to start reacting to InputManager updates. -
public void Dispose()
Unsubscribes from the InputManager events. Implements IDisposable; call when the resolver is no longer needed to avoid dangling event handlers. -
public void Update()
Primary per-frame (or periodic) entry point. Sets m_UpdateInProgress true to prevent event handlers from scheduling concurrent work. If m_ActionsDirty, calls RefreshActions() and raises EventActionRefreshed. If m_ConflictsDirty, calls ResolveConflicts() and raises EventConflictResolved. Clears the in-progress flag at the end. -
private void OnActionsChanged()
Event handler that marks both actions and conflicts dirty unless an update is currently in progress. -
private void OnControlSchemeChanged(InputManager.ControlScheme scheme)
Event handler that marks conflicts dirty unless an update is in progress (control scheme change can affect conflicts). -
private void OnPreResolvedActionChanged()
Event handler that marks conflicts dirty unless an update is in progress (pre-resolved flags/masks changed). -
private void RefreshActions()
Rebuilds m_SystemActions, m_UIActions and m_ModActions by iterating InputManager.instance.actions and placing each ProxyAction in the appropriate list: - not built-in -> mod actions
- built-in + isSystemAction -> system actions
-
built-in + not system -> UI actions
-
private void ResolveConflicts()
Resolves conflicts with priority order: system actions > UI actions > mod actions. Algorithm: - Reset m_HasConflict for UI and mod actions (system actions are left as-is but implicitly checked).
- For each enabled system action, compare against each enabled UI and mod action; mark secondary.m_HasConflict = true if InputManager.HasConflicts(...) reports a conflict.
- For each enabled UI action, compare against each enabled mod action similarly.
- After marking conflicts, call Apply() on all UI and mod States to push the resolved enable/mask into ProxyAction.ApplyState(enabled, preResolvedMask).
-
A local static helper Resolve(State primary, State secondary) invokes InputManager.HasConflicts(primary.m_Action, secondary.m_Action, primary.m_Action.preResolvedMask, secondary.m_Action.preResolvedMask) and sets secondary.m_HasConflict when conflicts are detected.
-
public void State.Reset()
Clears the m_HasConflict flag for reuse in a conflict resolution pass. -
public void State.Apply()
Applies the computed enabled state and the action's preResolvedMask to the underlying ProxyAction by calling ProxyAction.ApplyState(enabled, preResolvedMask).
Notes: - InputManager.HasConflicts(...) is used to detect conflicts between two ProxyAction instances given their masks. - Only UI and mod actions are applied (system actions are assumed authoritative and are not modified here).
Usage Example
// Typical lifecycle:
var resolver = new Game.Input.InputConflictResolution();
resolver.EventActionRefreshed += () => Debug.Log("Actions refreshed");
resolver.EventConflictResolved += () => Debug.Log("Conflicts resolved");
resolver.Initialize();
// In your game's update loop:
void Update()
{
resolver.Update(); // will refresh actions and resolve conflicts when needed
}
// When shutting down or unloading:
resolver.Dispose();
Additional integration notes: - Ensure InputManager.instance is initialized before calling Initialize(). - ProxyAction.ApplyState(enabled, mask) is used to apply pre-resolved enable/mask settings; the resolver only applies changes for UI and mod actions after conflict resolution. - The resolver is not thread-safe; it is intended to be used from the main thread where InputManager events are fired.