docs
Systems
Infrastructure
InputSystem
Architecture and Design

InputSystem Architecture

Design Patterns

  • Singleton: InputManager sets a static Instance in Awake, calls DontDestroyOnLoad, and destroys any duplicate. Other code reads the manager through InputManager.Instance.
  • Event-based notification (observer style): InputManager exposes Action<Vector3> delegates such as Clicked, Pressed, and Released. ClickDetector exposes an Action<Vector3> event, and DoubleClickDetector exposes an Action event. Subscribers attach with += and detach with -=.
  • Composition: InputManager creates and owns a ClickDetector and a DoubleClickDetector. ClickDetector receives the InputManager in its constructor and subscribes to its Pressed and Released delegates.
  • MonoBehaviour lifecycle: InputManager and InputHandler use Awake, Start, Update, and OnDisable.
  • Compile-time platform selection: InputManager.Update calls HandleTouch when UNITY_ANDROID is defined and HandleMouse otherwise.

Connections to Other Systems

  • UI system (UIEventFactory): InputHandler calls the UI event factory when a click or double-click occurs. The factory raises the matching UI events on the EventBus, which is how other systems receive them. This system does not subscribe to the EventBus itself.
  • World and UI objects (IInteractable): When a press hits a UI object, InputManager finds every IInteractable on that object and its parents and calls OnInteraction on each one.
  • EventBus: The UI event factory publishes to the EventBus. Listeners on the EventBus do not need a direct reference to this system.

Key Concepts

  • Press and release: A press is the start of a pointer interaction (mouse button down or touch began). A release is the end (mouse button up or touch ended).
  • Hold: Reported every frame while the pointer stays down, as Held.
  • Drag: Starts when the pointer moves more than dragThreshold pixels from the press position while held. Ends on release if a drag was in progress.
  • Click: A press and release where the elapsed time is at or below InputConstants.ClickThreshold (0.2 seconds) and no drag occurred.
  • Double-click: Two presses within the window set by doubleClickTime (0.3 seconds by default in InputManager). Presses are counted, not clicks.
  • Hit resolution: The raycast uses the EventSystem's RaycastAll and takes the first result, which the code describes as the closest object to the camera.

Event and Data Flow

Each frame, InputManager runs one of two paths. The order of events within a single release is fixed by the code.

Press (mouse down or touch began)
  InputManager.Pressed
  Raycast via EventSystem, call IInteractable.OnInteraction on hit
  DoubleClickDetector.RegisterClick(Time.time)
    -> OnDoubleClick -> InputManager.DoubleClicked

Hold (mouse held or touch moved/stationary)
  InputManager.Held
  If distance from press > dragThreshold and not yet dragging:
    InputManager.DragStarted
    DoubleClickDetector.Reset()
    ClickDetector.Reset()

Release (mouse up or touch ended)
  InputManager.Released
    ClickDetector.OnReleased
      If elapsed <= ClickThreshold -> ClickDetector.OnClick -> InputManager.Clicked
  If dragging:
    InputManager.DragEnded

InputHandler subscribes to Clicked and DoubleClicked and forwards each one to the UI event factory.

Thread Safety

The code shows no threading. All work happens on the Unity main thread in Update and in event callbacks.