Files
aego/modules/physics/res/docs/physics.ru.md
sanspie f22242e5aa
ci / release (push) Successful in 5m5s
ci-platforms / build (amd64, windows, windows-2022) (push) Skipped
ci-platforms / build (arm64, darwin, macos-15) (push) Skipped
ci-platforms / build (amd64, darwin, macos-15-intel) (push) Skipped
ci / checks (push) Successful in 4m41s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 7m14s
Stage 11g2–11g3: registry texts, CLI and the site in Russian (D348)
The remaining editor strings and undo step names; component, field, enum, setting, diagnostic and Script API texts under schema.*, enum.*, setting.*, diag.* and api.*; the launcher, the in-game Settings View with a Language setting, the CLI and aego schema show --lang. Every documentation page has a .ru.md translation; the site has a full Russian tree with hreflang, a language switch and ru/llms.txt; aego docs check --lang ru. New doc.tutorial and doc.recipe icons. Fix: an animator restored by a rewind prepares its controller before the replayed step.
2026-10-25 15:31:22 +03:00

264 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: physics
group: physics
group_title: Физика 2D
title: Физика 2D
---
# Физика 2D
Aego симулирует твёрдые 2D-тела собственным решателем. Тело — это узел с компонентом **«Тело 2D»**; форму ему задают коллайдеры на этом узле и его детях. Скрипты реагируют на контакты и опрашивают мир.
Физика работает во время игры и в `aego run`. В режиме правки ничего не движется, а панель «Сцена» показывает контуры коллайдеров и их проблемы.
Чтобы попробовать:
1. **Создать → Физика → Твёрдое тело** даёт падающий ящик.
2. **Создать → Физика → Статический коллайдер** даёт для него пол.
3. Нажмите «Играть».
---
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»](ref:physics.Body2D) | делает узел телом: `static`, `kinematic` или `dynamic` |
| [Прямоугольник](ref:physics.BoxCollider2D), [круг](ref:physics.CircleCollider2D), [капсула](ref:physics.CapsuleCollider2D), [многоугольник](ref:physics.PolygonCollider2D) и [«Коллайдер-линия 2D»](ref:physics.EdgeCollider2D) | формы |
| [«Соединение на расстоянии 2D»](ref:physics.DistanceJoint2D) | держит расстояние до тела `Target`, жёстко или как пружина |
| [«Шарнир 2D»](ref:physics.RevoluteJoint2D) | крепит к телу `Target` в точке `Anchor`, с необязательным ограничителем и мотором |
У каждого коллайдера есть `Offset`, `IsTrigger`, `Friction`, `Restitution` и `Density`.
- Капсулы лежат вдоль локальной оси X узла. `Length` включает закругления.
- Многоугольники выпуклые, с числом точек от 3 до 8.
- Коллайдеры-линии — это ломаные для геометрии уровня. `Loop` замыкает их. `OneSided` делает их твёрдыми только с той стороны, куда закручиваются точки: точки, идущие слева направо, тверды сверху.
`Type` тела определяет, как оно движется: `static` никогда не движется, `kinematic` движется по своей скорости и не замечает сил, `dynamic` реагирует на силы и контакты. Его скорость и то, активно ли оно, — состояние во время игры; оно перечислено на странице [«Тело 2D»](ref:physics.Body2D).
---
id: physics/hierarchy
title: Тела и иерархия
---
# Тела и иерархия
Коллайдер принадлежит ближайшему узлу с компонентом «Тело 2D» — самому узлу коллайдера или выше по иерархии. Поэтому одно тело можно собрать из нескольких дочерних узлов, у каждого свой коллайдер; масса, центр масс и инерция складываются из всех них. Коллайдер без тела выше становится отдельным статическим телом.
Позиция, поворот и равномерный масштаб коллайдера относительно его тела запекаются в форму. Прямоугольники и многоугольники принимают и неравномерный масштаб; кругам и капсулам нужен равномерный, иначе они сообщают [PHY001](ref:PHY001). Узлы под 3D-родителем не симулируются ([PHY005](ref:PHY005)).
Трансформация движущегося тела принадлежит физике. Записывайте её из `FixedUpdate` или через `Teleport`, и она применится как телепорт на следующем шаге с сохранением скорости. Запись из `Update` сообщается один раз для каждого тела ([PHY007](ref:PHY007)) и применяется на следующем шаге. Статические и кинематические тела следуют за своим узлом каждый шаг. Если во время игры перенести движущееся тело к другому родителю, оно создаётся заново с той же мировой позой и скоростью ([PHY006](ref: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`.
```aes
body := node.Get<Body2D>()
v := body.Velocity
body.SetVelocity(Vec2{x * Speed, v.Y})
body.ApplyImpulse(JumpImpulse)
```
## Движение тела
- Силы и момент действуют во время следующего шага физики. Вызывайте `ApplyForce` и `ApplyTorque` из `FixedUpdate`.
- Импульсы меняют скорость сразу, с учётом массы. Они подходят для прыжков и ударов.
- `MoveTo` приводит кинематическое тело в позу к концу следующего шага. `Teleport` переносит тело без проверки пути и сохраняет его скорость.
Все методы перечислены на странице [«Тело 2D»](ref:physics.Body2D).
## Запросы
Лучи, проверки отрезком и проверки перекрытия не замечают собственное тело вызывающего и пропускают триггеры. Они работают только во время игры. Функции, которые заполняют срез `out`, записывают не больше `len(out)` элементов, поэтому задайте размер среза один раз через `append` и используйте его повторно.
Все функции перечислены на странице [aego/physics](ref:aego/physics).
---
id: physics/settings
title: Настройки
---
# Настройки
![Настройки проекта → Физика с предпросмотром гравитации и контактов](shots/settings-physics.png)
**Настройки проекта → Физика** правят блок `physics` в `project.aego`: гравитацию, подшаги, итерации, жёсткость контактов, пороги сна, слои и матрицу. Пустое или нулевое поле берёт значение движка по умолчанию, оно показано серым. Подшаги и оба числа итераций принимают значения от 1 до 64. Изменения применяются при следующем запуске игры.
Высоким свободно стоящим стопкам и быстрым моторам нужен жёсткий профиль: `substeps=8` и `contactHertz=60`, примерно вдвое дороже для решателя. При стандартных 30 Гц и 4 подшагах свободная колонна выдерживает примерно двенадцать ящиков; кладка со смещением, как у кирпичей, стоит гораздо выше.
---
id: physics/editor
title: Инструменты редактора
---
# Инструменты редактора
Редактор рисует коллайдеры, контакты и силы и позволяет менять форму коллайдеров маркерами. Эти инструменты работают в панели «Сцена», а некоторые — и поверх идущей игры.
![Контуры коллайдеров и контакты поверх панели «Игра» во время игры](shots/physics-debug.png)
## Маркеры
Выберите узел с коллайдером, чтобы перетаскивать его стороны, радиус, длину или вершины. Двойной щелчок по ребру многоугольника добавляет вершину; Alt-щелчок по вершине удаляет её. Соединения показывают точки крепления на обоих телах. Каждое перетаскивание — один шаг отмены.
**«Подогнать под спрайт»** в «Инспекторе» коллайдеров-прямоугольников, кругов и капсул подгоняет форму под спрайт узла.
## Оверлеи
- Меню **Физика** включает отладочный оверлей: формы, контакты, ограничивающие прямоугольники, соединения, острова и дерево широкой фазы. В режиме правки рисуются только формы.
- **Векторы** (`V` в панели «Сцена») рисуют скорость, угловую скорость, силы, импульсы контактов, гравитацию и поля скриптов с `@export(gizmo="vector")`. Перетащите кончик стрелки поля, чтобы изменить значение.
- **Игра → Оверлеи** рисует те же слои поверх идущей игры, с игровой камерой.
## Проблемы и профилирование
- **Проблемы** перечисляют ошибки коллайдеров и соединений со ссылкой на узел. Сломанная геометрия не даёт запустить игру.
- **Профилировщик → Физика** показывает тела, пары, острова и время каждого этапа во время игры.
---
id: physics/lifecycle
title: Жизненный цикл
---
# Жизненный цикл
Что происходит с телами, формами и событиями контактов, когда сцена меняется во время игры.
| Действие во время игры | Результат |
|---|---|
| Удалить узел тела | его формы покидают мир на следующем шаге, события Exit — на том же шаге |
| Удалить дочерний коллайдер | форма удаляется, масса и инерция пересчитываются |
| Выключить узел | все формы под ним выключаются с событиями Exit; при включении Enter приходит на следующем шаге |
| Удалить «Тело 2D» | дочерние коллайдеры становятся статическими телами |
| Удалить коллайдер | форма удаляется с событием Exit |
| Изменить слой или маску | запрещённые пары заканчиваются на том же шаге |
| Изменить флаг триггера или геометрию | контакты формы заканчиваются, новые начинаются на следующем шаге |
| Добавить тело или коллайдер | подхватывается на следующем шаге и начинает в покое |
| Перенести движущееся тело к другому родителю | создаётся заново с мировой позой и скоростью, [PHY006](ref:PHY006) |
| Горячая перезагрузка скриптов | мир продолжает работать, обработчики привязываются заново по имени |
| Нативная пересборка | мир игры создаётся заново вместе с редактором |
| Остановить | мир уничтожается без событий Exit |
---
id: physics/world
title: Мир
---
# Мир
Физический мир продвигает все тела вместе с фиксированной частотой, по умолчанию 60 раз в секунду, и никогда — по времени кадра. Эта страница описывает, как он двигает тела и что значат параметры материалов.
## Шаги
Каждый шаг один раз находит контакты, а затем решает их в подшагах, по умолчанию в 4. Подшаг применяет гравитацию, расталкивает перекрывающиеся формы, двигает тела и гасит толчок, чтобы он не превратился в отскок. Больше подшагов — жёстче контакты; см. [Настройки](ref:physics/settings).
Тело проходит за шаг не больше заданного расстояния и угла. Маленьким быстрым телам стоит включить `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` истинно один кадр, а в кадре может быть ноль или два фиксированных шага. Читайте его в `Update`, а действуйте в `FixedUpdate`, или используйте `input.Down`.
## Коллайдер-круг сообщает о проблеме
Кругам и капсулам нужен равномерный масштаб. Меняйте поля коллайдера, а не растягивайте узел.
## Объекты проваливаются сквозь тонкий пол
Отметьте маленькие быстрые тела как `Bullet` или сделайте пол толще.
## Высокие башни шатаются
Используйте жёсткий профиль из раздела [Настройки](ref:physics/settings), сдвигайте ящики, как кирпичи, или соберите башню как одно тело.
## Ничего не сталкивается
Проверьте маски обоих тел и матрицу слоёв, а также то, что узел 2D и не находится под 3D-родителем.
## Движение кажется невесомым
Гравитация 9.81 предполагает, что единица — это примерно метр. Спрайт 64 пикселя при масштабе 64 — это одна единица.