Ввод и взаимодействие
Система ввода разделяет обнаружение ввода (мышь, клавиатура, геймпад и legacy navigation axes) и действия (перетаскивание, выделение, контекстное меню). Это позволяет менять привязки без переписывания логики и поддерживать разные устройства ввода.
Как устроен ввод
flowchart LR
A["Мышь /\nКлавиатура /\nГеймпад"] --> B["Определение\nрежима ввода"]
B --> C["Распознавание\nжеста"]
C --> D{"Какое\nдействие?"}
D --> E["Перетаскивание"]
D --> F["Контекстное меню"]
D --> G["Выделение"]
D --> H["Автоперенос"]
Слот сам не знает, что делать с вводом. Он пересылает сырые события (нажатие, отпускание, наведение) в InputEventRouter, который ищет подходящую привязку и выполняет действие.
Фазы нажатия
Система различает несколько типов нажатия по длительности и перемещению курсора:
flowchart TD
A["Нажатие"] --> B{"Что произошло дальше?"}
B -->|"Отпустили быстро\nи курсор не двигался"| C["Быстрый клик"]
B -->|"Держали дольше порога\n0.35 сек"| D["Долгое нажатие"]
B -->|"Курсор сдвинулся\nбольше 8 px"| E["Перетаскивание"]
| Фаза | Условие | Типичное действие |
|---|---|---|
| ClickShort | Быстро нажали и отпустили, курсор не сдвинулся | Автоперенос, выделение |
| ClickLong | Держали дольше порога, курсор не сдвинулся | Контекстное меню |
| Down | Момент нажатия | Начало перетаскивания |
| Up | Момент отпускания | Завершение перетаскивания |
Пороги настраиваются в InputEventRouter: _longClickThresholdSeconds (по умолчанию 0.35 сек) и _clickMoveTolerancePixels (по умолчанию 8 пикселей).
Профили привязок
Привязки настраиваются через ScriptableObject InteractionBindingsProfile. В нём есть pointer bindings, legacy KeyCode bindings, legacy Input Manager bindings по имени кнопки и опциональные Input Action bindings.
Привязки указателя (Pointer Bindings)
Каждая привязка состоит из: кнопка мыши + модификатор + фаза + действие.
| Кнопка | Модификатор | Фаза | Действие |
|---|---|---|---|
| ЛКМ | --- | ClickShort | Автоперенос |
| ЛКМ | --- | Down | Начать перетаскивание |
| ЛКМ | --- | Up | Завершить перетаскивание |
| ЛКМ | Ctrl | ClickShort | Переключить выделение |
| ЛКМ | Shift | ClickShort | Диапазонное выделение |
| ПКМ | --- | ClickShort | Контекстное меню |
Привязки Legacy Input Manager
Используйте LegacyInputActionBinding, если проект всё ещё работает через старый Input Manager и действие нужно задавать строковым именем кнопки, а не KeyCode.
Типичные имена: Submit, Cancel или любая своя кнопка из Project Settings > Input Manager.
| Имя кнопки | Фаза | Типичное действие |
|---|---|---|
| Submit | Down | Автоперенос или завершение drag |
| Cancel | Down | Отмена drag или закрытие UI |
Эти привязки опрашиваются через InputEventRouter и требуют включённой поддержки Legacy Input Manager в Player Settings.
Они не заменяют InputActionBinding: это отдельный путь для старой системы ввода.
Привязки Input Action
Для опциональных hotkeys и gamepad-специфичных сценариев: привязка Input System Action к действию инвентаря.
Mixed setup поддерживается, но важно помнить, что InputAction-зависимые функции всё равно ожидают, что для этой сцены/flow настроен новый input pipeline.
Если сцена намеренно остаётся на StandaloneInputModule, pointer и navigation там могут работать, а часть InputAction-функций — нет.
Режим ввода
Система автоматически определяет текущий режим ввода:
| Режим | Как активируется | Поведение |
|---|---|---|
| Mouse | Клик мышью или движение мыши | Фокус через наведение, стандартные события указателя |
| Navigation | Стрелки, WASD, Submit/Cancel, Tab, D-pad геймпада | Фокус через EventSystem.selectedGameObject, навигация между слотами |
Переключение происходит автоматически и в legacy input, и в новом Input System. Когда активен режим Navigation, InputEventRouter поддерживает фокус на слоте --- если текущий выделенный объект стал неактивным, система находит ближайший доступный слот.
Переопределение привязок для инвентаря
Каждый инвентарь может иметь свои привязки через компонент InventoryExtraInteractionBinder. Это полезно, когда у торговца и у игрока разное поведение по клику.
Если на инвентаре нет InventoryExtraInteractionBinder, используется дефолтный InteractionBindingsProfile из InputEventRouter.
Частичный сброс (Split Drop)
При перетаскивании стека можно сбросить часть предметов в слот, не прекращая перетаскивание. Остаток остаётся "в руке", визуал и счётчик обновляются автоматически.
Для этого используется встроенное действие SplitDropAction:
| Параметр | Описание | По умолчанию |
|---|---|---|
_splitCount |
Сколько предметов отщеплять за раз | 1 |
_dropPolicyOverride |
Переопределение drop policy для этой операции | --- |
Настройка привязки
Добавьте PointerBinding в InteractionBindingsProfile:
| Кнопка | Модификатор | Фаза | Действие |
|---|---|---|---|
| ЛКМ | Shift | Down | SplitDropAction |
Порядок привязок
Привязка Shift + ЛКМ должна стоять выше обычной привязки ЛКМ (Start/Complete drag), чтобы модификатор матчился первым.
Как работает
- Игрок берёт стек из 10 предметов (обычный drag).
- Зажимает Shift и кликает по пустому слоту.
- 1 предмет переносится через стандартный конвейер (движок переноса → события).
- Перетаскивание продолжается с 9 предметами, визуал обновляется.
- Когда в стеке остаётся 1 предмет, Shift+Click выполняет обычный
CompleteDrag.
Если целевой слот занят и не может принять предмет, операция откатывается — стек остаётся без изменений.
Справочник классов
| Класс | Роль |
|---|---|
InputEventRouter |
Синглтон: маршрутизирует ввод к привязкам |
InteractionBindingsProfile |
SO-профиль с pointer, legacy и Input Action привязками |
SlotInputAdapter |
Компонент на слоте: пересылает сырые события |
InputModalityTracker |
Определяет текущий режим ввода (Mouse / Navigation) и в legacy, и в Input System конфигурации |
PointerBinding |
Привязка: кнопка + модификатор + фаза + действие |
KeyBinding |
Legacy KeyCode привязка к действию |
LegacyInputActionBinding |
Привязка старого Input Manager по имени кнопки к действию |
InputActionBinding |
Привязка Input System Action к действию |
InventoryExtraInteractionBinder |
Переопределение привязок для конкретного инвентаря |
SplitDropAction |
Действие: сбросить часть стека, не прекращая drag |
SlotInteractionAction |
Базовый класс действия (наследуйте для кастомных) |