22 KiB
id, group, group_title, title
| id | group | group_title | title |
|---|---|---|---|
| physics | physics | Физика 2D | Физика 2D |
Физика 2D
Aego симулирует твёрдые 2D-тела собственным решателем. Тело — это узел с компонентом «Тело 2D»; форму ему задают коллайдеры на этом узле и его детях. Скрипты реагируют на контакты и опрашивают мир.
Физика работает во время игры и в aego run. В режиме правки ничего не движется, а панель «Сцена» показывает контуры коллайдеров и их проблемы.
Чтобы попробовать:
- Создать → Физика → Твёрдое тело даёт падающий ящик.
- Создать → Физика → Статический коллайдер даёт для него пол.
- Нажмите «Играть».
id: physics/units title: Единицы и оси
Единицы и оси
Физика работает в единицах мира. Одна единица — это любой размер, который вы выберете для своей игры; лучше всего ведут себя формы от 0.1 до 10 единиц. render.pixelsPerUnit в project.aego используется только для размера импортированных спрайтов по умолчанию, Camera2D.Zoom по умолчанию и «Подогнать под спрайт»; физика его никогда не читает, поэтому его изменение не меняет того, как что-либо падает.
Оси совпадают с осями 2D-сцены: +X вправо, +Y вниз, положительные углы поворачивают по часовой стрелке. Гравитация по умолчанию — (0, 9.81), она направлена вниз по экрану. Нормали и скорости в событиях и запросах используют те же оси, поэтому у пола под телом нормаль с отрицательным Y.
id: physics/components title: Компоненты
Компоненты
Эти компоненты делают узел частью симуляции. У каждого есть своя страница в справочнике со всеми полями.
| Компонент | Назначение |
|---|---|
| «Тело 2D» | делает узел телом: static, kinematic или dynamic |
| Прямоугольник, круг, капсула, многоугольник и «Коллайдер-линия 2D» | формы |
| «Соединение на расстоянии 2D» | держит расстояние до тела Target, жёстко или как пружина |
| «Шарнир 2D» | крепит к телу Target в точке Anchor, с необязательным ограничителем и мотором |
У каждого коллайдера есть Offset, IsTrigger, Friction, Restitution и Density.
- Капсулы лежат вдоль локальной оси X узла.
Lengthвключает закругления. - Многоугольники выпуклые, с числом точек от 3 до 8.
- Коллайдеры-линии — это ломаные для геометрии уровня.
Loopзамыкает их.OneSidedделает их твёрдыми только с той стороны, куда закручиваются точки: точки, идущие слева направо, тверды сверху.
Type тела определяет, как оно движется: static никогда не движется, kinematic движется по своей скорости и не замечает сил, dynamic реагирует на силы и контакты. Его скорость и то, активно ли оно, — состояние во время игры; оно перечислено на странице «Тело 2D».
id: physics/hierarchy title: Тела и иерархия
Тела и иерархия
Коллайдер принадлежит ближайшему узлу с компонентом «Тело 2D» — самому узлу коллайдера или выше по иерархии. Поэтому одно тело можно собрать из нескольких дочерних узлов, у каждого свой коллайдер; масса, центр масс и инерция складываются из всех них. Коллайдер без тела выше становится отдельным статическим телом.
Позиция, поворот и равномерный масштаб коллайдера относительно его тела запекаются в форму. Прямоугольники и многоугольники принимают и неравномерный масштаб; кругам и капсулам нужен равномерный, иначе они сообщают PHY001. Узлы под 3D-родителем не симулируются (PHY005).
Трансформация движущегося тела принадлежит физике. Записывайте её из FixedUpdate или через Teleport, и она применится как телепорт на следующем шаге с сохранением скорости. Запись из Update сообщается один раз для каждого тела (PHY007) и применяется на следующем шаге. Статические и кинематические тела следуют за своим узлом каждый шаг. Если во время игры перенести движущееся тело к другому родителю, оно создаётся заново с той же мировой позой и скоростью (PHY006).
id: physics/layers title: Слои столкновений
Слои
До 32 именованных слоёв и пары, которые сталкиваются, объявляются в project.aego или в Настройках проекта → Физика:
physics {
layers=[Default, Ground, Player, Enemy]
collide {
Player=[Ground, Enemy]
Enemy=[Ground, Player]
}
}
Матрица симметрична: Player=[Enemy] позволяет и врагам задевать игроков. Без блока collide каждый слой сталкивается со всеми остальными. Неизвестное имя слоя в collide — ошибка загрузки.
Тело хранит свой слой как индекс, поэтому при переименовании слоя все тела остаются на нём; если стереть имя, индекс сохраняется. Две формы сталкиваются, когда Mask каждого из тел принимает слой другого и матрица разрешает эту пару. Если во время игры изменить слой или маску, запрещённые ими контакты заканчиваются на следующем шаге.
id: physics/events title: События
События
Объявите метод с одним из этих имён в любом скрипте на узле тела или на узле коллайдера:
func OnCollisionEnter(other NodeRef, c physics.Contact)
func OnCollisionStay(other NodeRef, c physics.Contact)
func OnCollisionExit(other NodeRef, c physics.Contact)
func OnTriggerEnter(other NodeRef)
func OnTriggerExit(other NodeRef)
Событие получают оба участника, каждый со своей стороны. other — узел другого тела; c.Normal направлена от другого тела к получателю, поэтому пол под вами сообщает c.Normal.Y < 0. c.SelfCollider и c.OtherCollider называют узлы коллайдеров. События выполняются после шага физики, до того как script.events_fixed завершает фиксированный тик.
OnCollisionStay вызывается каждый шаг, пока два тела соприкасаются, и только если его обрабатывает какой-нибудь скрипт; лучше считать Enter и Exit. Exit приходит и тогда, когда тело удалено или выключено; other.IsAlive() тогда ложно.
Удалять узлы внутри обработчика безопасно: удаление происходит после того, как отработали все обработчики.
id: physics/scripting title: Скрипты
Скрипты
Скрипты двигают тела через компонент «Тело 2D» и спрашивают у мира, что где находится, через aego/physics.
body := node.Get<Body2D>()
v := body.Velocity
body.SetVelocity(Vec2{x * Speed, v.Y})
body.ApplyImpulse(JumpImpulse)
Движение тела
- Силы и момент действуют во время следующего шага физики. Вызывайте
ApplyForceиApplyTorqueизFixedUpdate. - Импульсы меняют скорость сразу, с учётом массы. Они подходят для прыжков и ударов.
MoveToприводит кинематическое тело в позу к концу следующего шага.Teleportпереносит тело без проверки пути и сохраняет его скорость.
Все методы перечислены на странице «Тело 2D».
Запросы
Лучи, проверки отрезком и проверки перекрытия не замечают собственное тело вызывающего и пропускают триггеры. Они работают только во время игры. Функции, которые заполняют срез out, записывают не больше len(out) элементов, поэтому задайте размер среза один раз через append и используйте его повторно.
Все функции перечислены на странице aego/physics.
id: physics/settings title: Настройки
Настройки
Настройки проекта → Физика правят блок physics в project.aego: гравитацию, подшаги, итерации, жёсткость контактов, пороги сна, слои и матрицу. Пустое или нулевое поле берёт значение движка по умолчанию, оно показано серым. Подшаги и оба числа итераций принимают значения от 1 до 64. Изменения применяются при следующем запуске игры.
Высоким свободно стоящим стопкам и быстрым моторам нужен жёсткий профиль: substeps=8 и contactHertz=60, примерно вдвое дороже для решателя. При стандартных 30 Гц и 4 подшагах свободная колонна выдерживает примерно двенадцать ящиков; кладка со смещением, как у кирпичей, стоит гораздо выше.
id: physics/editor title: Инструменты редактора
Инструменты редактора
Редактор рисует коллайдеры, контакты и силы и позволяет менять форму коллайдеров маркерами. Эти инструменты работают в панели «Сцена», а некоторые — и поверх идущей игры.
Маркеры
Выберите узел с коллайдером, чтобы перетаскивать его стороны, радиус, длину или вершины. Двойной щелчок по ребру многоугольника добавляет вершину; Alt-щелчок по вершине удаляет её. Соединения показывают точки крепления на обоих телах. Каждое перетаскивание — один шаг отмены.
«Подогнать под спрайт» в «Инспекторе» коллайдеров-прямоугольников, кругов и капсул подгоняет форму под спрайт узла.
Оверлеи
- Меню Физика включает отладочный оверлей: формы, контакты, ограничивающие прямоугольники, соединения, острова и дерево широкой фазы. В режиме правки рисуются только формы.
- Векторы (
Vв панели «Сцена») рисуют скорость, угловую скорость, силы, импульсы контактов, гравитацию и поля скриптов с@export(gizmo="vector"). Перетащите кончик стрелки поля, чтобы изменить значение. - Игра → Оверлеи рисует те же слои поверх идущей игры, с игровой камерой.
Проблемы и профилирование
- Проблемы перечисляют ошибки коллайдеров и соединений со ссылкой на узел. Сломанная геометрия не даёт запустить игру.
- Профилировщик → Физика показывает тела, пары, острова и время каждого этапа во время игры.
id: physics/lifecycle title: Жизненный цикл
Жизненный цикл
Что происходит с телами, формами и событиями контактов, когда сцена меняется во время игры.
| Действие во время игры | Результат |
|---|---|
| Удалить узел тела | его формы покидают мир на следующем шаге, события Exit — на том же шаге |
| Удалить дочерний коллайдер | форма удаляется, масса и инерция пересчитываются |
| Выключить узел | все формы под ним выключаются с событиями Exit; при включении Enter приходит на следующем шаге |
| Удалить «Тело 2D» | дочерние коллайдеры становятся статическими телами |
| Удалить коллайдер | форма удаляется с событием Exit |
| Изменить слой или маску | запрещённые пары заканчиваются на том же шаге |
| Изменить флаг триггера или геометрию | контакты формы заканчиваются, новые начинаются на следующем шаге |
| Добавить тело или коллайдер | подхватывается на следующем шаге и начинает в покое |
| Перенести движущееся тело к другому родителю | создаётся заново с мировой позой и скоростью, PHY006 |
| Горячая перезагрузка скриптов | мир продолжает работать, обработчики привязываются заново по имени |
| Нативная пересборка | мир игры создаётся заново вместе с редактором |
| Остановить | мир уничтожается без событий Exit |
id: physics/world title: Мир
Мир
Физический мир продвигает все тела вместе с фиксированной частотой, по умолчанию 60 раз в секунду, и никогда — по времени кадра. Эта страница описывает, как он двигает тела и что значат параметры материалов.
Шаги
Каждый шаг один раз находит контакты, а затем решает их в подшагах, по умолчанию в 4. Подшаг применяет гравитацию, расталкивает перекрывающиеся формы, двигает тела и гасит толчок, чтобы он не превратился в отскок. Больше подшагов — жёстче контакты; см. Настройки.
Тело проходит за шаг не больше заданного расстояния и угла. Маленьким быстрым телам стоит включить Bullet: их контакты заглядывают вперёд на расстояние, которое они проходят за один шаг.
Каждое тело и каждая форма проверяются при создании. Недопустимые числа, отрицательные размеры, вогнутые многоугольники и отрезки нулевой длины отклоняются с ошибкой, и мир остаётся прежним.
Материалы
| Параметр | Значение | Когда соприкасаются две формы |
|---|---|---|
Friction |
0 — лёд, 1 — резина | sqrt(a·b) |
Restitution |
0 — остановка, 1 — отскок с полной скоростью | max(a, b) |
Density |
масса на квадратную единицу | — |
Очень медленные отскоки не восстанавливаются, поэтому тела в покое остаются в покое.
Сон
Группа соприкасающихся тел засыпает, когда все они какое-то время двигались медленно. Группу будит контакт с активным телом, сила, импульс, телепорт или новое соединение.
Детерминизм
Одна и та же игра на том же процессоре с тем же вводом каждый раз даёт один и тот же результат. На этом держится перемотка игры в редакторе.
id: physics/pitfalls title: Частые ошибки
Частые ошибки
Это ошибки, из-за которых физика чаще всего ощущается неправильной. Для каждой сказано, что вы видите и что нужно изменить.
Динамическое тело дрожит при движении
Если двигать динамическое тело через SetPosition из Update, вы боретесь с решателем. Используйте SetVelocity, силы или Teleport из FixedUpdate.
Прыжок иногда теряется
Читайте действие input.Pressed("Jump") прямо в FixedUpdate. Нажатие сохраняется до первого фиксированного шага, даже если в кадре отрисовки не было ни одного шага, и не повторяется в следующих шагах. input.Down означает удержание, а не новое нажатие: это не замена событию прыжка. Если другой контекст ввода поглощает действие, проверьте его и назначения клавиш. См. Ввод: кадры и фиксированные шаги.
Коллайдер-круг сообщает о проблеме
Кругам и капсулам нужен равномерный масштаб. Меняйте поля коллайдера, а не растягивайте узел.
Объекты проваливаются сквозь тонкий пол
Отметьте маленькие быстрые тела как Bullet или сделайте пол толще.
Высокие башни шатаются
Используйте жёсткий профиль из раздела Настройки, сдвигайте ящики, как кирпичи, или соберите башню как одно тело.
Ничего не сталкивается
Проверьте маски обоих тел и матрицу слоёв, а также то, что узел 2D и не находится под 3D-родителем.
Движение кажется невесомым
Гравитация 9.81 предполагает, что единица — это примерно метр. Спрайт 64 пикселя при масштабе 64 — это одна единица.

