← Модуль 9/Game feel
EN
Модуль 9 · Дизайн (теория)

Game feel

Невидимая инженерия, которую инженеры хронически недооценивают. Математика тайминга — нативный MathML (без библиотек).
конспект~16 мин🏠 лаба
Суть за 20 секунд
Game feel — моментальная тактильная удовлетворённость — это в основном невидимая инженерия: отзывчивость ввода плюс стек крошечных «juice»-трюков (coyote time, jump buffering, hit-stop, screen shake, squash-and-stretch, частицы). Ничего из этого нет в «правилах» игры — это разница между мёртвым прыжком и живым. Инженеры это недооценивают, а ровно это часто и отделяет инди-хит от тех-демо.

Контекст

Термин закрепил Steve Swink в книге «Game Feel» (2008): ощущение управления виртуальным объектом в реальном времени — то, что нельзя свести к правилам, но что игрок чувствует руками. Канонические примеры — Celeste и Mario: их прыжок ощущается «правильным» не из-за формул движения, а из-за десятков подкрученных мелочей вокруг них. Девиз ремесла — «juice it or lose it»: без слоя обратной связи технически корректная механика воспринимается мёртвой.

Ключевая мысль, которую инженер должен принять: то, что делает симуляция, и то, что воспринимает игрок — это две разные вещи, и game feel живёт именно в зазоре между ними.

Механизм

Game feel собирается из двух семейств приёмов: прощение ввода (input forgiveness) и обратная связь (feedback).

Input forgiveness — честность контролей без объяснений

Обе техники игроку не объясняют — он просто чувствует, что «контроли честные». Это и есть иллюзия честности: поблажка, замаскированная под отзывчивость.

Feedback — продать «вес» и событие

Общий знаменатель всего стека — разведение «что делает симуляция» и «что воспринимает игрок». Симуляция остаётся честной и детерминированной; слой feel живёт поверх неё и врёт ровно настолько, насколько нужно для ощущения.

Математика тайминга

Почему «окно прощения» вообще нужно — считается арифметикой кадров. Бюджет одного кадра при 60 fps:

tframe=160 s≈16.67 ms

Время реакции человека — порядка 200 ms. В кадрах это:

200 ms16.67 ms / frame≈12 frames

То есть между «вижу край» и «палец нажал» проходит около дюжины кадров — поэтому окно прощения порядка ~10+ кадров ощущается не как чит, а как компенсация физиологической задержки игрока.

Вторая базовая формула feel — сглаживание камеры (lerp к цели каждый кадр):

pnew=p+(target−p)·k

Это удобно, но привязано к частоте кадров: один и тот же k на 30 и 144 Гц даёт разную скорость догона. Frame-rate-independent вариант делает коэффициент функцией dt:

pnew=p+(target−p)·(1−e−k·dt)

Почему именно так — в хардкоре про математику.

Таймлайн прыжка: окна прощения сход с края приземление coyote ~6 кадров после buffer ~5 кадров до нажатие «поздно» нажатие «рано» оба нажатия «не в кадр» — но прыжок всё равно срабатывает

🕹 В какие игры поиграть — и что заметить

Game feel нельзя прочитать — его ловят пальцами. Четыре платформера, от одной базовой ручки до целого стека ощущений; по каждому — что подкручено и что заметить руками (от простого к сложному).

Super Mario Bros. 1985 · variable jump · фундамент

Откуда всё пошло. Высота прыжка зависит от длительности нажатия (держишь — выше, отпустил рано — срезали восходящую скорость) плюс инерция: Марио не стартует и не тормозит мгновенно. Одна-две ручки, но именно они делают управление «вкусным» — без них прыжок мёртвый, с фиксированной высотой.

🎮 Сыграй: любой Mario (хоть SMB, хоть Odyssey). Сделай два прыжка подряд — коротко тапни и зажми кнопку: высота разная (variable jump). Разбегись и резко развернись — Марио проскальзывает по инерции, не клеится к нулю. Вот два самых базовых feel-knob'а.

Celeste 2018 · стек прощения · канон

Эталон современного game feel, задокументированный самим разработчиком (Maddy Thorson). Стек «прощения»: coyote time (прыжок ~0.1 с / ≈6 кадров после схода с края), jump buffering (нажатие до приземления срабатывает в кадр касания) и corner correction (бьёшься головой об угол — игра подвигает тебя вбок мимо него; клипнул угол дэшем — подкидывает на полку). Всё «фуджит» в пользу игрока ровно настолько, чтобы казаться отзывчивым, а не магнитным.

🎮 Сыграй: Celeste (или демо). Прыгни с края заведомо поздно — coyote спасёт. Прыгай впритык к низкому потолку в углу — заметь, как тебя подталкивает мимо угла (corner correction), вместо того чтобы «бонкнуть» и упасть. Включи Assist Mode — увидишь, что игра уже прощает, ассист лишь усиливает.

Super Meat Boy 2010 · точность · feel под давлением

Обратный полюс: минимум поблажек, максимум отзывчивости. Управление настолько прямое и цепкое (быстрый разгон, липкие стены), что смерть всегда читается как «я сам». Ключ — мгновенный респаун: ноль загрузки между попытками, поэтому feel ощущается на каждой из сотен смертей, а не раз в минуту.

🎮 Сыграй: Super Meat Boy (демо/полная). Умри 20 раз подряд на одном экране и заметь: между смертью и новой попыткой нет паузы — это часть feel, а не UX-мелочь. Прижмись к стене — мгновенное цепкое сцепление и отскок, без «ватного» лага.

Hollow Knight 2017 · feel боя, не только прыжка

Feel выходит за пределы движения — в бой. Удар гвоздём даёт hit-stop (микрозаморозку на контакте → «масса встретила массу») и knockback (отдача толкает и тебя), а удар вниз по врагу или шипе — pogo: отскок вверх, превращающий бой в платформинг. Плюс экранная тряска и частицы. Тот же стек, но на боёвке.

🎮 Сыграй: Hollow Knight (демо). Бей врага в упор — почувствуй микропаузу удара (hit-stop) и отдачу. Прыгни на врага/шипы и бей вниз — отскочишь (pogo); попробуй пропрыгать на гвозде по цепочке шипов. Feel — это не только прыжок.

Хардкор · дизайн: почему forgiveness работает и 12 принципов Disneyможно пропустить

Перцептивная честность: время реакции ~200 ms

Игрок не управляет в реальном времени — он управляет с лагом собственной нервной системы (~200 ms, ~12 кадров на 60 fps). Без прощения каждое «я же нажал!» — это правда: намерение было вовремя, моторика опоздала. Coyote time и jump buffering закрывают разрыв между perceived (когда игрок «решил») и actual (когда пришёл ввод). Отсюда иллюзия честности: игра кажется отзывчивой именно потому, что тайно подыгрывает — но в пределах человеческой задержки, не больше, иначе чувствуется «магнит».

12 принципов Disney в реальном времени

Классическая анимация — готовый словарь feel-приёмов, переложенный на интерактив:

  • Squash & stretch — деформация массы при ускорении/приземлении; продаёт упругость и вес.
  • Anticipation — микро-замах перед действием (приседание перед прыжком) — глаз успевает «прочитать» намерение.
  • Follow-through & overlap — части тела/плаща догоняют корпус после остановки; убирает «робота».

Разница с фильмом: в кино аниматор владеет таймингом, в игре тайминг диктует игрок — поэтому принципы становятся процедурными (squash как функция вертикальной скорости, anticipation как пара кадров перед стартом).

Juice-стек как чеклист

Практический приём: брать сырую механику и прогонять по списку — input forgiveness (coyote, buffer), hit feedback (hit-stop, shake), motion (squash, anticipation, follow-through), ambient (particles, camera lerp/lookahead, sound). Каждый пункт добавляется отдельным тумблером, чтобы можно было выключить и почувствовать вклад (ровно это делает Lab 09).

Хардкор · математика: кадры↔мс и геометрическое затухание камерыможно пропустить

Кадры ↔ миллисекунды

Все feel-тайминги удобнее держать в кадрах, но мерить в миллисекундах (иначе на 144 Гц «6 кадров» — это другое физическое время). Перевод:

nframes=tmstframe,tframe≈16.67 ms (60 fps)

Окно прощения ~10 кадров ≈ 167 ms — меньше времени реакции (~200 ms), поэтому компенсирует моторную задержку, не выходя в «читерство». Hit-stop задают как N кадров (типично 2–6): на N кадров замораживается геймплейный тик, удар читается как столкновение масс. Слишком большой N — игра «залипает», слишком малый — эффекта нет.

Lerp как геометрическое затухание

Наивный кадровый lerp p ← p + (target − p)·k за m кадров оставляет ошибку:

em=(target−p0)·(1−k)m

Это геометрическая прогрессия: ошибка падает как (1−k)m. Но m — это число кадров, а не время. На 144 Гц за ту же секунду кадров в ~2.4 раза больше, чем на 60 Гц, значит (1−k) применяется в ~2.4 раза чаще — камера догоняет ощутимо быстрее. Один и тот же k → разный feel на 30/60/144 Гц. Это и есть баг наивного lerp.

Frame-rate-independent форма

Чинится переходом к непрерывной модели: затухание — это экспонента от времени, а не от числа шагов. Подставляя реальный dt:

e(t)=e0·e−k·t⇒k'=1−e−k·dt

Теперь коэффициент шага зависит от dt, и за одинаковое время ошибка падает одинаково при любой частоте кадров. Тот же приём — для любого экспоненциального сглаживания (damping скорости, фейды), не только камеры.

Хардкор · инженерия: juice без потери детерминизмаможно пропустить

Feel ломает наивный игровой цикл сильнее, чем кажется. Что держать в голове:

  • Hit-stop морозит геймплей, но не UI. Заморозка должна останавливать физик-тик/симуляцию, но не презентационный слой: меню, курсор, иногда сами частицы продолжают жить. Если морозить общий timescale, замирает всё, включая интерфейс — выглядит как фриз/баг. Разведи feel-эффекты и симуляционный тик.
  • Детерминизм. Coyote/buffer/hit-stop меняют тайминг входов, а в сетевой/replay-игре это часть состояния. Считай окна в кадрах фиксированного тика (а не в реальных секундах), храни счётчики в симуляционном состоянии — иначе replay и netcode разъезжаются. Screen shake и частицы держи чисто на стороне презентации: они не должны влиять на симуляцию.
  • Frame-rate-independent тайминг. Все feel-константы — в миллисекундах/секундах, в шаге умножаются на dt (см. хардкор по математике). Тогда game feel одинаков на 30/60/144 Гц. Исключение — фиксированный физик-тик: там кадр стабилен, и окна можно держать прямо в кадрах тика.
  • A/B juice-toggle (Lab 09). Архитектурно полезно вынести весь juice за один флаг/слой, чтобы включать-выключать без правки геймплея. Это и тестовый стенд (почувствовать вклад), и страховка детерминизма: если toggle меняет исход симуляции — значит juice протёк в логику, и это баг.
Аналогия
Game feel — это разница между машиной с усилителем руля и подвеской и без них. Двигатель тот же, маршрут тот же, физика та же — но вождение совсем другое. Coyote time — это люфт руля, который прощает неточное движение; hit-stop — отдача, которую чувствуешь телом; squash-stretch и particles — подвеска, которая отрабатывает каждую кочку. Уберёшь всё это — поедешь, но руки запомнят «мёртвую» машину.
Почему это важно
Это самая «не-инженерная» тема ремесла — и самая высокорычажная под цель «понимать, что геймдевам реально нужно». AI-for-games инженер без чувства game feel построит технически-правильное, но мёртвое: симуляция корректна, играть невозможно. И это редкое место, где AI/ML почти никогда не ответ — feel это руками подобранные константы и ремесло, а не обучаемая функция. Хорошее напоминание, что ML — это инструмент в чужом ремесле, а не его центр.
🏠 Лаба — пощупать game feel
Интерактивная лаба без кода: играбельный платформер прямо в браузере (на телефоне — кнопки на экране). Тащи ползунок coyote-time, включай-выключай jump buffer / hit-stop / screen shake / squash — и чувствуй разницу на той же механике. Открыть лабу →
Математика тайминга (кадры↔реакция, зависимость lerp от FPS) — в хардкор-вкладке выше; почувствовать вживую — секции «🕹» и «🔧» ниже.
🔧 Запусти и поковыряй — на домашнем компе
Во что поиграть и что заметить — выше (🕹). Здесь — для тех, кто хочет крутить ручки feel сам:
🔧 Поковырять (debug) ~40 мин, PICO-8 / Godot
Возьми открытый платформер — «Celeste Classic» (оригинал на PICO-8, исходник открыт) или любой Godot-темплейт. Найди константу coyote-time и поставь её в 0 — пробеги тот же кусок: контроли мгновенно «глохнут». Верни 6 кадров — оживает. Так же выключи hit-stop и squash. Ты не пишешь систему — крутишь чужие ручки и ловишь вклад каждой.
🧪 Потестить (глазами QA) ~15 мин
Сыграй как тестировщик отзывчивости: на каждом крае спрашивай «прыжок честный?»; меряй на глаз input lag; ищи, где буфер/coyote не срабатывают (двойной прыжок, у стены, на движущейся платформе) — типичные дыры feel.
Чеклист: обнулил coyote в коде и ощутил «глухоту»; вернул — ожило; нашёл хотя бы один кейс, где прощение не работает. Канонический доклад про вклад juice — «Juice it or lose it» (Jonasson & Purho).
🔁 За пределами игр — куда это переносится
Суть game feel — развести «что делает система» и «что воспринимает человек» и инженерить именно восприятие. Это вся UX-инженерия:

Фронтенд / UX: optimistic UI (показать результат до ответа сервера = тот же jump buffer/coyote), skeleton-экраны, perceived performance, прощение ввода в формах.

ML / AI: стриминг вывода LLM (токены по мере генерации — воспринимаемая латентность падает в разы при той же реальной); «думает…»-индикаторы; вся UX-обвязка вокруг медленных моделей — это game feel для AI-продукта.

Распределённые / сети: latency hiding, prefetch, спекулятивное исполнение — то же «perceived ≠ actual».

Принцип: воспринимаемое ≠ фактическое; инженерь восприятие, а не только систему — и компенсируй задержку человека, не выходя в «магнит».

Связи
пересечение
Классика vs ML — game feel это руками подобранные константы и ремесло, а не обучение; яркий пример «AI здесь не нужен» и де-центрирования ML.
пересечение
ECS / data-oriented — feel живёт в бюджете кадра и тайминге тика: hit-stop и frame-rate-independent сглаживание — это про тот же 16.67 ms и фиксированный шаг.
пересечение
Doom / BSP — скорость рендера Doom напрямую делала ощущение: высокий, стабильный фреймрейт — это тоже game feel, ещё до всякого juice.
Вопросы пытливого ума
Почему coyote time ощущается «честным», хотя технически это поблажка игроку?
Потому что компенсирует реальную физиологическую задержку. Игрок «решает» прыгнуть, когда видит край, а ввод приходит на ~200 ms (≈12 кадров) позже — моторика опаздывает, не намерение. Окно прощения ~6 кадров возвращает игроку то время, которое съела его же нервная система. Субъективно это не «мне дали лишнее», а «контроли наконец-то отзывчивые». Честность здесь — про совпадение perceived и actual, а не про буквальное правило.
Почему hit-stop продаёт «вес»?
Мозг читает паузу как столкновение масс. В реальности тяжёлые объекты при ударе на миг «слипаются» и теряют скорость; короткая заморозка (2–6 кадров) имитирует этот микро-момент инерции. Без неё попадание мгновенно и «бесплотно» — энергии как будто нет. С ней удар получает физическую читаемость: глаз успевает зафиксировать контакт, и тело достраивает ощущение силы. Дёшево по реализации, огромно по эффекту.
Можно ли A/B-тестить feel?
Да — ровно это Lab 09 (juice on/off за один тумблер). Но осторожно с метрикой: «feel» плохо ловится количественно. Время прохождения или ретеншн могут не отличаться, хотя версия с juice субъективно живее — потому что вы измеряете не то. Лучше работают качественные сигналы (что игроки говорят, куда смотрят, где бросают) и прямое сравнение «вкл/выкл» на себе. A/B полезен, чтобы поймать, что вы случайно сделали хуже, а не чтобы «оптимизировать feel» по одному числу.
Обучается ли feel машинно?
По сути — нет, и это отличный пример «AI здесь не нужен». Feel — это горстка руками подобранных констант (сколько кадров coyote, сколько hit-stop, какой k у камеры) плюс художественное суждение «ощущается живым». Нет ни датасета, ни целевой функции, которую честно оптимизировать: «удовлетворённость от прыжка» не дифференцируема. ML может помочь по краям (подсказать частицы, сгенерить ассет), но саму подкрутку делает человек на ощупь. Тема, где ремесло бьёт обучение.
Почему инженеры это недооценивают?
Потому что feel невидим, не записан в «правилах» и плохо измеряется. В спеке механики его нет: «прыжок = импульс вверх» — формально полно, а играть мёртво. Инженерная культура ценит то, что можно специфицировать и протестировать числом, а feel — это субъективное «ощущается правильно», которое не проходит код-ревью. Плюс он диффузный: не одна фича, а двадцать мелочей, каждая по отдельности «незначительная». Итог — слой, который делает или ломает игру, систематически выпадает из инженерного поля зрения.
Что почитать