{"schemaVersion":1,"record":{"key":"lesson/input-and-feedback","type":"lesson","id":"input-and-feedback","lang":"ru","title":"Ввод и обратная связь","summary":"Превращаем нажатия в игровые намерения и показываем игроку, какое действие принято, отклонено или выполнено.","updatedAt":"2026-10-20","status":"active","url":"https://gamemechanics.pro/ru/lessons/input-and-feedback/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/input-and-feedback.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/input-and-feedback.md","aliases":[],"tags":["input","feedback","accessibility"],"sourceIds":["source-663cb05191120f23"],"sources":[{"id":"source-663cb05191120f23","title":"Godot: Using InputEvent","url":"https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html","verifiedAt":null}],"sections":[{"id":"prerequisites","title":"Что нужно знать","body":"Урок подходит для первого управляемого прототипа. Нужны обработчик ввода и одно действие, например взаимодействие с дверью. Цель: игрок понимает результат нажатия, а игровой код не зависит от конкретной клавиши."},{"id":"principle","title":"Принцип","body":"Разделите физический сигнал, игровое намерение и результат. Клавиша E или кнопка геймпада порождает `interact`. Игровая логика решает, можно ли открыть дверь. Интерфейс сообщает, что произошло. Такой путь проще проверять, чем обработчик клавиши, который сразу двигает дверь, воспроизводит звук и меняет инвентарь.\n\nСистема действий позволяет назначать несколько устройств на одно намерение. В Godot эту роль выполняет InputMap; порядок обработки событий также позволяет интерфейсу перехватывать ввод до игрового мира. См. [Using InputEvent](https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html).\n\nДля движения обычно важно удержание. Для переключения меню или использования предмета нужен фронт нажатия, то есть переход из состояния «не нажато» в «нажато». Если выполнять переключение каждый кадр удержания, одно нажатие будет многократно открывать и закрывать меню.\n\n<span id=\"пример-закрытая-дверь\"></span>"},{"id":"example","title":"Практический пример","body":"### Закрытая дверь\n\nОпределим три результата: дверь открылась, нужен ключ, игрок слишком далеко. Логика возвращает результат, а слой представления выбирает подходящий текст, звук или анимацию.\n\n```text\ntryInteract(player, door):\n    if distance(player, door) > interactRange:\n        return outOfRange\n    if door.locked and not player.hasKey:\n        return needsKey\n    door.open = true\n    return opened\n\nonActionPressed(interact):\n    result = tryInteract(player, selectedDoor)\n    presentInteractionResult(result)\n```\n\nВ учебной сцене разместите две двери: одну рядом, вторую вне радиуса. Сначала проверьте принятие намерения без эффектов, затем добавьте короткую подпись причины отказа. Не запускайте анимацию успешного открытия до решения игровой логики.\n\nЕсли в сцене несколько дверей, явно определите выбор цели: ближайшая доступная, объект под прицелом или выделенный объект. Покажите выбранную дверь до нажатия. Это помогает отличить ошибку выбора цели от ошибки проверки ключа."},{"id":"mistakes","title":"Частые ошибки","body":"Один и тот же ввод не должен одновременно нажимать кнопку меню и стрелять в мире. Закрытие окна не должно оставлять движение навсегда включённым. При потере фокуса предусмотрите очистку удерживаемых действий: событие отпускания может прийти не туда, где его ожидают.\n\nНе сообщайте об отказе только красным цветом или только тихим звуком. В примере добавьте текст причины и различимое состояние двери. Для часто повторяющегося отказа ограничьте частоту сигналов, иначе каждое удержание превратится в поток звуков.\n\nНе добавляйте буфер ввода автоматически ко всем действиям. Отложенный прыжок иногда помогает управлению, а отложенное подтверждение покупки или выхода может быть неожиданным. Срок жизни намерения должен быть частью правила конкретного действия."},{"id":"checks","title":"Проверка результата","body":"- Клавиатура и геймпад вызывают одно игровое действие.\n- Удержание кнопки не повторяет одиночное действие каждый кадр.\n- Меню получает ввод без одновременного действия в мире.\n- После потери и возврата фокуса движение не застревает.\n- Причина отказа понятна без различения цвета и без звука.\n- Выбранная цель видна до подтверждения."},{"id":"agent-task","title":"Задание для ИИ-агента","body":"> Раздели ввод, проверку взаимодействия и представление результата для двери. Сохрани существующие привязки управления. Определи поведение удержания, интерфейса и потери фокуса. Добавь проверки трёх исходов и объясни, как игрок узнаёт причину отказа. Не добавляй задержку или буферизацию без отдельного правила."}],"relations":[{"type":"requires","direction":"outgoing","label":"Перед началом","key":"lesson/game-loop","title":"Игровой цикл и время","url":"https://gamemechanics.pro/ru/lessons/game-loop/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/game-loop.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/game-loop.md"},{"type":"requires","direction":"incoming","label":"Продолжить изучение","key":"lesson/state-machines","title":"Состояния и переходы","url":"https://gamemechanics.pro/ru/lessons/state-machines/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/state-machines.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/state-machines.md"},{"type":"requires","direction":"incoming","label":"Продолжить изучение","key":"lesson/game-feel","title":"Game feel: читаемое действие","url":"https://gamemechanics.pro/ru/lessons/game-feel/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/game-feel.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/game-feel.md"},{"type":"requires","direction":"incoming","label":"Продолжить изучение","key":"lesson/teaching-a-mechanic","title":"Обучение одной механике через уровень","url":"https://gamemechanics.pro/ru/lessons/teaching-a-mechanic/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/teaching-a-mechanic.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/teaching-a-mechanic.md"},{"type":"requires","direction":"incoming","label":"Продолжить изучение","key":"lesson/game-accessibility","title":"Базовая доступность игровой сессии","url":"https://gamemechanics.pro/ru/lessons/game-accessibility/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/lesson/game-accessibility.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/lesson/game-accessibility.md"},{"type":"explains","direction":"outgoing","label":"Применение принципа","key":"mechanic/voice-audio--family-01","title":"Прямые голосовые команды","url":"https://gamemechanics.pro/ru/knowledge/mechanic/voice-audio--family-01/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/mechanic/voice-audio--family-01.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/mechanic/voice-audio--family-01.md"},{"type":"explains","direction":"outgoing","label":"Применение принципа","key":"mechanic/point-and-click--family-43","title":"Способы ввода и выбора действия","url":"https://gamemechanics.pro/ru/knowledge/mechanic/point-and-click--family-43/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/mechanic/point-and-click--family-43.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/mechanic/point-and-click--family-43.md"},{"type":"contains","direction":"incoming","label":"Учебные маршруты","key":"path/first-prototype","title":"Первый проверяемый прототип","url":"https://gamemechanics.pro/ru/learn/first-prototype/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/path/first-prototype.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/path/first-prototype.md"},{"type":"requires","direction":"incoming","label":"Продолжить изучение","key":"path/level-design","title":"Левел-дизайн","url":"https://gamemechanics.pro/ru/learn/level-design/","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/path/level-design.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/path/level-design.md"},{"type":"uses","direction":"outgoing","label":"Источники в подборке","key":"resource/godot-input","title":"Godot: обработка ввода","url":"https://gamemechanics.pro/ru/resources/#resource-godot-input","jsonUrl":"https://gamemechanics.pro/api/v1/knowledge/ru/resource/godot-input.json","markdownUrl":"https://gamemechanics.pro/content/knowledge/ru/resource/godot-input.md"}],"placements":[],"supersededBy":[],"attributes":{"category":"foundations","level":"beginner","minutes":6},"endsAt":null,"provenance":"Авторский материал gamemechanics.pro. Учебные примеры требуют проверки в своём проекте.","license":"CC-BY-4.0","codeLicense":"MIT","attribution":"gamemechanics.pro contributors"}}