LerpworksAcademy
На этой странице

Урок по шагам

Движение: скорость, ускорение и шаг времени

26 шагов

  • Зачем это
  • Три стрелки: положение, скорость, ускорение
  • Игра движется шагами
  • Интегрирование: шаги вместо плавной линии
  • Фиксированный шаг физики
  • Траектория: куда упадёт граната
  • В движках и Blender
  • Где ломается
  • Связи: та же идея в других областях
  • Главное

Математика и физика › Физика движения

Движение: скорость, ускорение и шаг времени

Нужно знать заранее: Векторы: стрелки, которые складывают

Этот урок есть в курсе «Физика для игр».

Всё, что в игре движется, — мяч, машина, граната, камера — описывают три стрелки: где предмет, куда и как быстро он едет и как меняется его скорость. Игра не видит движение сплошной линией: она сдвигает предметы маленькими шагами, кадр за кадром. Разберём, как из этих шагов складывается движение, почему всё умножают на время кадра, почему высота прыжка может зависеть от мощности компьютера и зачем физике свои, ровные часы.

Зачем это

Если двигать предметы «на глаз», игра ведёт себя по-разному на разных компьютерах. На мощном персонаж бегает вдвое быстрее, на слабом граната не долетает, после секундного подвисания мяч проваливается сквозь пол. Все эти ошибки из одного места: как игра переводит плавное движение в шаги.

Это первый урок курса «Физика для игр». Понадобятся векторы как шаги и умножение вектора на число. Как устроен весь кадр игры с точки зрения движка — в уроке «Кадр и тик»; здесь — математика движения.

Три стрелки: положение, скорость, ускорение

Представь, что по свежему снегу прошёл человек, а мы каждые полсекунды отмечали, где он стоит, — получилась цепочка следов. По следам можно прочитать всё его движение.

  • Положение — где остался след. Это точка, от начала мира до неё ведёт вектор.
  • Скорость (velocity) — насколько меняется положение за секунду. Это тоже вектор: у него есть направление (куда идёт) и длина (как быстро). Следы, оставленные каждые полсекунды в 1.5 м друг от друга, значат 3 метра в секунду, 3 м/с. Длину вектора скорости показывает спидометр, а направление — куда смотрят колёса.
  • Ускорение (acceleration) — насколько меняется скорость за секунду. Мяч, который падает, каждую секунду прибавляет 9.8 м/с скорости вниз: ускорение свободного падения — 9.8 метра в секунду за секунду, 9.8 м/с².

Цепочка одна: ускорение меняет скорость, скорость меняет положение. Поэтому, чтобы толкнуть предмет, игра меняет его скорость, а чтобы тянуть его вниз — даёт постоянное ускорение.

Ускорение — это любое изменение скорости, не только разгон. Торможение — ускорение против движения. А поворот — ускорение вбок: машина проходит круг с одной цифрой на спидометре, но направление скорости меняется, и тебя прижимает к двери. На круге радиусом r при скорости v ускорение смотрит в центр и равно v² / r.

Попробуй

Следы оставлены через равные промежутки времени. Синяя стрелка у следа — скорость, умноженная на промежуток: куда бы пришёл следующий шаг, если бы скорость не менялась. Жёлтая — ускорение (в своём масштабе). Нажми на след, чтобы увидеть его числа. Сравни, как меняются промежутки при разгоне, торможении и на повороте.


Как читать следы

Промежуток между соседними следами — это скорость, умноженная на время между ними. Если промежутки одинаковые, скорость постоянна. Если растут — предмет разгоняется, и растут они на одну и ту же величину. Пример: разгон с места с ускорением 2 м/с², следы через 0.5 с. Следы ложатся на 0, 0.25, 1, 2.25 и 4 м, промежутки — 0.25, 0.75, 1.25, 1.75 м. Каждый следующий длиннее на 0.5 м: это ускорение × (0.5 с)².

На повороте промежутки равны, а стрелки скорости поворачиваются. Ускорение там есть, хотя спидометр стоит на месте.

Игра движется шагами

Мультфильм в блокноте: на каждой странице человечек чуть сдвинут, и при быстром листании он бежит. Игра работает так же: 60 раз в секунду она сдвигает всё немного и рисует новую картинку — кадр. Время от прошлого кадра до этого называют временем кадра, Δt (дельта-тэ, delta time). При 60 кадрах в секунду Δt = 1/60 ≈ 0.0167 с, это 16.7 мс на весь кадр.

Каждый кадр игра делает два действия — те же, что мы видели на снегу, только в обратную сторону:

скорость = скорость + ускорение × Δt     // ускорение меняет скорость
позиция  = позиция  + скорость  × Δt     // скорость меняет положение

Всё это векторы, каждую ось считают отдельно. Мяч летит со скоростью (4, 3) м/с, кадр длится 0.02 с: позиция сдвигается на (0.08, 0.06) м. Гравитация (0, −9.8) м/с² за тот же кадр меняет скорость на (0, −0.196) м/с, и мяч чуть сильнее клонится вниз.

Если персонаж идёт по направлению из стика, направление нормализуют до длины 1 и только потом умножают на скорость. Иначе по диагонали (1, 1) он побежит в 1.41 раза быстрее — ловушка из урока про векторы.

Почему умножают на Δt

Проще всего двигать персонажа на 5 см каждый кадр. Но число кадров в секунду зависит от компьютера:

Кадров в секундуΔtПо 5 см за кадр3 м/с × Δt
300.033 с1.5 м/с10 см за кадр, 3 м/с
600.017 с3 м/с5 см за кадр, 3 м/с
1440.007 с7.2 м/с2.1 см за кадр, 3 м/с

Без Δt на мощном компьютере герой бегает почти в пять раз быстрее, чем на слабом, и замедляется, когда в кадре много взрывов. С Δt скорость задают в метрах в секунду, а каждый кадр берёт от неё свою долю: короткий кадр — короткий шаг, длинный — длинный. За секунду шаги всегда складываются в 3 метра.

Интегрирование: шаги вместо плавной линии

Собирать движение из маленьких шагов называют интегрированием: по скорости восстанавливают путь, по ускорению — скорость. Способ выше — самый простой, метод Эйлера. Он делает одно допущение: весь кадр скорость постоянна. Настоящий мяч меняет скорость непрерывно, а в игре — ступеньками. От этого появляется ошибка, и она зависит от длины шага.

Порядок двух строк важен

Две строки можно выполнить в любом порядке, и результаты разные:

  • Явный Эйлер: сначала позиция по старой скорости, потом новая скорость. Шаг берёт скорость в начале кадра.
  • Полунеявный Эйлер (semi-implicit): сначала новая скорость, потом позиция по ней. Шаг берёт скорость в конце кадра.

Проверим на броске. Мяч подбросили вверх со скоростью 7 м/с. Настоящая высота — ровно 2.5 м. Считаем с разным числом шагов в секунду:

Шагов в секундуЯвный ЭйлерПолунеявныйТочно
102.86 м2.16 м2.50 м
302.62 м2.38 м2.50 м
602.56 м2.44 м2.50 м
1442.52 м2.48 м2.50 м

По дороге вверх мяч тормозит, и скорость в начале каждого шага больше, чем в конце. Явный Эйлер шагает по большей скорости и залетает выше, полунеявный — по меньшей и не долетает. Ошибка пропорциональна длине шага: вдвое короче шаг — вдвое меньше промах. К вершине она составляет g × Δt × t / 2, где t — время подъёма: при 30 шагах в секунду — 12 см.

Для игры это значит: высота прыжка зависит от частоты кадров. Возьмём полунеявный Эйлер, как в движках: полка на высоте 2.45 м при 144 кадрах в секунду достаётся (2.48 м), а при 30 — нет (2.38 м). С явным Эйлером наоборот: на слабом компьютере прыжок выходит выше, а не ниже. В любом случае высота зависит от кадров. Умножение на Δt здесь не спасает: оно выравнивает среднюю скорость, но не ошибку шага.

Почему тогда движки берут полунеявный Эйлер, хотя он тоже ошибается? Он устойчив. Явный Эйлер на каждом шаге чуть добавляет энергии: пружина качается всё шире, спутник уходит с орбиты по спирали. Полунеявный держит размах качелей и орбиту. Подробно — в уроке про пружины.

Попробуй

Мяч подброшен вверх со скоростью 7 м/с. График — высота по времени. Пунктир — настоящая парабола, точки — где мяч оказался после каждого шага. Меняй число шагов в секунду и смотри, кто достаёт до полки на 2.45 м. Галочка добавит шаг с поправкой Δt²/2 — о нём ниже, «под капотом».


Под капотом: путь — площадь под графиком скорости

Нарисуй график скорости по времени. Если скорость постоянна, путь — прямоугольник: высота — скорость, ширина — время. 3 м/с за 2 с — площадь 6, это и есть 6 метров. Для любой скорости путь — площадь под графиком.

При постоянном ускорении график скорости — наклонная прямая: от v₀ в начале шага до v₀ + aΔt в конце. Фигура под ней — трапеция, её площадь — средняя из двух высот на ширину:

путь = (v₀ + (v₀ + aΔt)) / 2 × Δt = v₀Δt + aΔt² / 2

Эйлер заменяет трапецию прямоугольником. Явный берёт высоту по левому краю, полунеявный — по правому. Промах за шаг — треугольник с катетами Δt и aΔt, площадью aΔt²/2. За n шагов треугольники складываются: n × aΔt²/2 = a × Δt × t / 2, ведь nΔt = t. Отсюда ошибка, пропорциональная шагу.

Шаг «позиция += скорость × Δt + ускорение × Δt² / 2» точен при любом Δt, но только пока ускорение постоянно, как у брошенного мяча. У пружины и сопротивления воздуха ускорение меняется внутри шага, трапеция превращается в кривую, и точной формулы нет. Тогда берут шаги короче или хитрее: метод Верле, Рунге — Кутты. Для игр обычно хватает полунеявного Эйлера с ровным шагом.

Фиксированный шаг физики

Раз результат зависит от длины шага, пусть шаг будет всегда одним и тем же. Так устроен фиксированный шаг (fixed timestep): физика считает ровными шагами, например по 1/60 с, отдельно от кадров. Кадры приходят когда получится, а физика живёт по своим часам.

Копилка времени

Представь копилку. Каждый кадр кидает в неё монету — своё время кадра, монеты разного размера. Физика тратит время только одинаковыми купюрами по 16.7 мс: пока в копилке хватает на купюру, делает шаг.

копилка = копилка + время_кадра
пока копилка ≥ шаг:
    шаг физики на время «шаг»
    копилка = копилка − шаг

При 40 кадрах в секунду (25 мс) и шаге 16.7 мс: в первом кадре один шаг и 8.3 мс в остатке, во втором 33.3 мс — два шага, остаток 0, дальше снова один. При 144 кадрах в секунду (6.9 мс) шаг случается раз в два-три кадра, в остальных физика не считается вовсе. За секунду всегда ровно 60 шагов.

Что это даёт:

  • Одинаковый результат везде. Прыжок одной высоты на любом компьютере, полка достаётся у всех или ни у кого.
  • Повтор. Те же нажатия на тех же шагах дают ту же игру. На этом держатся записи повторов и сетевые игры, где компьютеры должны прийти к одному итогу.
  • Устойчивость. Пружины, стопки ящиков и машины настраивают под один шаг, и они не взрываются от случайно длинного кадра.

Попробуй

Сверху — кадры по реальному времени, снизу — шаги физики по игровому. Линия соединяет шаг с кадром, который его посчитал; полоска под кадром — остаток в копилке. Выбери, как ведут себя кадры. Потом двигай «расчёт шага»: сколько реального времени занимает один шаг физики. Больше длины шага — и начинается спираль. Галочка «не больше 8 шагов» ставит предохранитель.


Сглаживание между шагами

У копилки есть цена. При 144 кадрах в секунду и 60 шагах физики мяч стоит на месте два-три кадра подряд, потом прыгает: движение идёт рывками. Лечат интерполяцией: игра помнит два последних шага и рисует предмет между ними. Долю берут из копилки: остаток / шаг. Осталось 4 мс из 16.7 — рисуем на 0.24 пути от прошлого шага к последнему.

Картинка при этом отстаёт от физики не больше чем на один шаг, 16.7 мс. Глаз этого не замечает, а рывки замечает сразу. Сглаживают только отрисовку: физика, столкновения и попадания живут на своих шагах.

Спираль смерти

Копилка честно доплачивает шаги за медленный кадр, и в этом ловушка. Пусть отрисовка занимает 5 мс, а один шаг физики считается 20 мс и описывает 16.7 мс игры. Каждый шаг делает кадр длиннее, длинный кадр кладёт в копилку больше времени, больше времени — больше шагов. Кадры растут: 25 мс, 25, 45, 45, 65, 85, 105… Игра тонет: кадров всё меньше, пока она не застынет. Это спираль смерти.

Предохранителей два, и оба жертвуют временем игры:

  • Не больше N шагов за кадр. Лишнее время из копилки выбрасывают. Игра начинает идти медленнее реального времени, как в замедленной съёмке, но не застывает.
  • Не больше N секунд в кадре. После долгой загрузки или паузы в копилку кладут, скажем, не больше трети секунды, а не 5 секунд разом.

Слишком длинный шаг

Даже ровный шаг может быть слишком длинным для быстрого предмета. Пуля летит 300 м/с, и за шаг 1/60 с она перелетает на 5 м. Стена толщиной 20 см попадает между двумя положениями, и столкновения не случится: пуля проходит насквозь. Если физика шагает временем кадра, одно подвисание на полсекунды даёт шаг в полсекунды, и падающий ящик проносится сквозь пол. Как это ловят и чинят — урок про проваливание быстрых тел.

Траектория: куда упадёт граната

У брошенного предмета ускорение постоянно — гравитация вниз. Поэтому по горизонтали он летит ровно, как по снегу с одинаковыми промежутками, а по вертикали — как подброшенный мяч: вверх, всё медленнее, и обратно. Вместе это парабола. Путь предмета называют траекторией.

Для постоянного ускорения есть точная формула положения в любой момент — та самая трапеция из «Под капотом»:

позиция(t) = старт + скорость₀ × t + ускорение × t² / 2

Граната вылетает со скоростью 20 м/с под углом 45°. Скорость раскладывают на две оси через синус и косинус: по 14.1 м/с вперёд и вверх. Вверх она летит 14.1 / 9.8 = 1.44 с и поднимается на 10.2 м. Вся дуга длится 2.89 с, и за это время граната пролетает вперёд 14.1 × 2.89 = 40.8 м. Под 45° бросок по ровной земле улетает дальше всего. В ту же точку можно попасть двумя углами: пологим и навесным, например 30° и 60°.

Прицел: нарисовать дугу заранее

Пунктир траектории у прицела гранатомёта — это та же формула: игра подставляет t = 0, 0.05, 0.1 с… и соединяет точки. Между соседними точками проверяют, не задевает ли отрезок стену или землю, и там рисуют метку падения.

Тонкость: сама граната летит шагами физики, а дуга посчитана точно. При полунеявном Эйлере и 30 шагах в секунду граната падает на 30 см ближе метки. Чтобы прицел не врал, дугу считают теми же шагами, что и физика, или бросок двигают по формуле, а не физикой.

В движках и Blender

Где ломается

  • На мощном компьютере всё быстрее, на слабом медленнее. Движение за кадр без Δt. Задавай скорость в секунду и умножай на Δt.
  • Прыжок то достаёт до уступа, то нет. Физика шагает временем кадра, и ошибка шага разная. Фиксированный шаг.
  • При высокой частоте кадров предметы дёргаются. Физика с фиксированным шагом без сглаживания. Включи интерполяцию отрисовки.
  • Игра всё сильнее тормозит и застывает под нагрузкой. Спираль смерти: шаг физики считается дольше, чем длится. Предел шагов за кадр, упрощение физики.
  • После подвисания ящик провалился сквозь пол. Один огромный Δt. Предел времени кадра и подшаги.
  • Метка прицела не совпадает с местом падения. Дуга посчитана формулой, граната — шагами. Считай их одинаково.
  • Пружина раскачивается всё сильнее и улетает. Явный Эйлер добавляет энергию. Полунеявный Эйлер и шаг короче.

Главное

  • Положение, скорость и ускорение — три вектора. Ускорение меняет скорость, скорость меняет положение, каждое — за секунду.
  • Поворот — тоже ускорение: меняется направление скорости, а не спидометр.
  • Игра двигает всё шагами: скорость += ускорение × Δt, позиция += скорость × Δt. Δt переводит «в секунду» в «за кадр».
  • Метод Эйлера ошибается пропорционально шагу. Полунеявный (сначала скорость) устойчив, поэтому его берут движки.
  • Фиксированный шаг даёт одинаковую физику на любом компьютере. Копилка времени решает, сколько шагов сделать в кадре, остаток сглаживает отрисовку.
  • Шаг, который считается дольше, чем длится, топит игру в спирали. Предел шагов за кадр меняет застывание на замедление.
  • При постоянном ускорении путь — парабола, и её точная формула с t²/2 рисует дугу прицела.

Проверь себя

8 вопросов. В профиль идёт лучший результат, проходить можно сколько угодно.

1. Персонаж каждый кадр сдвигается на 0.1 м. При 30 кадрах в секунду он бежит 3 м/с. Как быстро он побежит при 120 кадрах в секунду?

2. Машина едет по кругу, и спидометр всё время показывает 60 км/ч. Есть ли у неё ускорение?

3. Следы оставлены через каждые 0.5 с. Промежутки между ними: 0.5, 1, 1.5, 2 м. Что можно сказать о движении?

4. В игре персонаж прыгает, физика считается временем кадра полунеявным Эйлером. Уступ на высоте 2.45 м при 144 кадрах в секунду достаётся, а при 30 — нет. Что поможет лучше всего?

5. Физика с фиксированным шагом 1/60 с, игра рисует 144 кадра в секунду. Мяч движется рывками. Почему и что сделать?

6. Один шаг физики на 1/60 с (16.7 мс) под нагрузкой стал считаться 22 мс. Предела шагов за кадр нет. Что будет?

7. Пуля летит 400 м/с, шаг физики 1/60 с. Иногда она проходит сквозь стену толщиной 30 см. Почему?

8. Граната летит под действием одной гравитации. Прицел рисует дугу точной формулой, а физика двигает гранату полунеявным Эйлером при 30 шагах в секунду. Что увидит игрок?

Что-то осталось непонятным? Выдели этот кусок текста и нажми «Спросить про это». Вопрос уйдёт автору, и это место перепишут понятнее.