Rigidbody2D: гравитация и движение по физике
Хочешь, чтобы герой падал, прыгал, отскакивал? Добавь Rigidbody2D — компонент, который отдаёт объект во власть физического движка.
Суть:
Rigidbody2Dделает объект физическим телом: на него действует гравитация, он имеет скорость и массу. Есть три типа: Dynamic (полная физика), Kinematic (двигается кодом, но участвует в столкновениях), Static (неподвижный, для стен). Физическое движение делают в FixedUpdate.
До этого мы двигали объект, напрямую меняя transform.position. Но реальная игровая физика — гравитация, инерция, отскоки — так не делается. Для неё есть Rigidbody2D. Добавил его на объект — и движок Box2D начинает симулировать тело: оно падает под гравитацией, копит скорость, сталкивается с другими.
Три типа тел решают разные задачи:
- Dynamic — полноценное физическое тело. Падает, его можно толкать силами. Герой, ящики, мячи.
- Kinematic — не подчиняется гравитации и силам, но двигается кодом и участвует в столкновениях. Платформы, движущиеся преграды.
- Static — вообще не двигается, экономит ресурсы. Стены, земля, статичные препятствия.
Как работает под капотом
Каждый шаг физики (в FixedUpdate) движок берёт скорость тела, двигает его, применяет гравитацию, проверяет столкновения:
Шаг физики (Dynamic тело): velocity.y += gravity * fixedDeltaTime (гравитация копит скорость вниз) position += velocity * fixedDeltaTime (тело двигается) проверить столкновения, оттолкнуть (не дать пройти сквозь пол)
Двигать Rigidbody напрямую через transform.position — ошибка: это «телепорт» мимо физики. Правильно менять velocity или применять силы AddForce. И только в FixedUpdate, ведь физика идёт фиксированным шагом.
using UnityEngine;
public class Jumper : MonoBehaviour
{
[SerializeField] private float jumpForce = 7f;
private Rigidbody2D rb;
void Awake() { rb = GetComponent<Rigidbody2D>(); }
void Update()
{
if (Input.GetButtonDown("Jump"))
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
}Симулируем падение под гравитацией на чистом Python — это та же интеграция скорости и позиции, что внутри Box2D:
# Тело падает под гравитацией; шаг физики фиксирован
gravity = -9.8
fixed_dt = 1 / 50 # 50 шагов физики в секунду
vy = 0.0 # вертикальная скорость
y = 10.0 # стартовая высота
step = 0
while y > 0 and step < 100:
vy += gravity * fixed_dt # гравитация копит скорость вниз
y += vy * fixed_dt # двигаем тело
step += 1
if step % 10 == 0:
print(f"шаг {step}: высота {y:.2f}, скорость {vy:.2f}")
print(f"Упал на землю за {step} шагов физики")Та же логика на Python ▶ — гравитация не двигает тело сразу, она копит скорость, а уже скорость двигает тело. Поэтому падение ускоряется. Ровно это делает Rigidbody2D каждый шаг FixedUpdate.
Частые ошибки
- Двигать Dynamic-тело через transform.position. Это конфликтует с физикой: объект дёргается и проходит сквозь стены. Меняй
velocityилиAddForce. - Применять силы в Update. Физику трогают в FixedUpdate. В Update только читают ввод и ставят флаг.
- Стены без Static. Если земля — Dynamic-тело, она сама упадёт под гравитацией. Стены и пол делай Static.
- Кэшировать Rigidbody через GetComponent каждый кадр. Получи ссылку один раз в Awake и храни.
Best practices
- Получай
Rigidbody2Dодин раз вAwakeчерезGetComponentи сохраняй в поле. - Подвижный герой — Dynamic, движущиеся платформы — Kinematic, статичная геометрия — Static.
- Прыжок: читай нажатие в Update, но меняй
velocityаккуратно; для длительных сил используйAddForceв FixedUpdate.
Итоги: Rigidbody2D отдаёт объект физическому движку. Типы тел — Dynamic, Kinematic, Static — под разные роли. Физику двигают через velocity и AddForce в FixedUpdate, а не через transform.position. Гравитация копит скорость, а скорость двигает тело — отсюда ускорение падения.
Continuous Collision Detection: почему пуля пролетает сквозь стену
У дискретной физики есть коварная ловушка. Между двумя шагами симуляции быстрый объект — пуля, прыгающий герой на большой скорости — может за один шаг переместиться сразу за тонкую стену, так и не оказавшись внутри неё ни на одном кадре. Движок просто не заметил столкновения: вот объект перед стеной, а вот уже за ней. Это называется туннелированием. Лекарство — режим Continuous в настройке Collision Detection у Rigidbody2D: вместо проверки только в точках-кадрах движок проверяет весь путь объекта между ними, как непрерывную линию. Continuous дороже по расчётам, поэтому включай его только там, где он нужен — для быстрых пуль и стремительных персонажей, а не для всех тел подряд. Для медленных объектов хватает обычного дискретного режима.