Использование физики Jolt

Введение

The Jolt physics engine was added as an alternative to the existing Godot Physics physics engine in 4.4. Jolt is developed by Jorrit Rouwe with a focus on games and VR applications. Previously it was available as an extension but is now built into Godot. By default, new projects will use it as the physics engine.

The existing extension is now considered in maintenance mode. That means bug fixes will be merged, and it will be kept compatible with new versions of Godot until the built-in module has feature parity with the extension. The only thing missing at this point is related joints, which you can read about on this page. The extension can be found here on GitHub and in Godot's asset library.

Чтобы изменить 3D-физический движок на Jolt Physics, установите для параметра Project Settings > Physics > 3D > Physics Engine значение Jolt Physics. После этого нажмите кнопку Save & Restart. После повторного открытия редактора 3D-сцены должны использовать Jolt для физики.

Заметные отличия от Физики Годо

Между существующим движком Godot Physics и Jolt существует множество различий.

Совместная собственность

Текущие интерфейсы узлов 3D-сочленений не совсем соответствуют интерфейсу собственных сочленений Jolt. В связи с этим ряд свойств сочленений не поддерживаются, в основном те, которые связаны с настройкой мягких пределов сочленений.

Неподдерживаемые свойства:

  • PinJoint3D: bias, damping, impulse_clamp

  • HingeJoint3D: bias, softness, relaxation

  • SliderJoint3D: angular_\*, \*_limit/softness, \*_limit/restitution, \*_limit/damping

  • ConeTwistJoint3D: bias, relaxation, softness

  • Generic6DOFJoint3D: *_limit_*/softness, *_limit_*/restitution, *_limit_*/damping, *_limit_*/erp

В настоящее время выдается предупреждение, если задать для этих свойств значения, отличные от значений по умолчанию.

Однокорпусные суставы

В Godot можно исключить одно из тел сочленения для двухчастичного сочленения и фактически сделать "the world" другим телом. Однако путь к узлу, которому вы назначаете своё тело (node_a вместо node_b), игнорируется. Godot Physics всегда будет вести себя так, как будто вы назначили его node_a, и поскольку node_a также определяет систему отсчёта для пределов сочленения, в результате вы получите инвертированные пределы и потенциально странную форму предела, особенно если ваши пределы допускают как линейные, так и угловые степени свободы.

Jolt будет вести себя так, как будто тело назначено узлу node_b, где node_a представляет "the world". Существует настройка проекта Physics > Jolt Physics 3D > Joints > World Node, которая позволяет включить это поведение, если вам нужна совместимость с существующим проектом.

Пределы столкновения

Jolt (и другие подобные физические движки) использует то, что Jolt называет "выпуклым радиусом", для улучшения производительности и поведения типов обнаружения столкновений, которые Jolt использует для выпуклых фигур. Другие физические движки (включая Godot) могут называть их "отступами от столкновений". Godot предоставляет их как свойство margin для каждого класса, производного от Shape3D, но сам Godot Physics не использует их ни для чего.

В других движках эти поля столкновения иногда (как описано в документации Godot) фактически добавляют "оболочку" вокруг фигуры, слегка увеличивая её размер и одновременно скругляя рёбра/углы. Однако в Jolt эти поля сначала используются для сжатия фигуры, а затем применяется "оболочка", в результате чего рёбра/углы также скругляются, но без увеличения размера фигуры.

Чтобы избежать необходимости вручную настраивать это свойство поля, поскольку его значение по умолчанию может быть проблематичным для небольших фигур, модуль Jolt предоставляет настройку проекта Physics > Jolt Physics 3D > Collisions > Collision Margin Fraction, которая умножается на наименьшую ось AABB фигуры для расчета фактического поля. В этом случае свойство поля фигуры используется в качестве верхней границы.

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

Стабилизация Баумгарте

Стабилизация Баумгарте — это метод, позволяющий разрешить проникающие тела и подтолкнуть их к состоянию, когда они едва касаются друг друга. В физике Godot это работает как пружина. Это означает, что тела могут ускоряться, что может привести к их проскоку и полному разделению. В методе Jolt стабилизация применяется только к положению, а не к скорости тела. Это означает, что проскок невозможен, но разрешение проникновения может занять больше времени.

Силу этой стабилизации можно настроить с помощью настройки проекта Physics > Jolt Physics 3D > Simulation > Baumgarte Stabilization Factor. Установка этой настройки проекта в значение 0.0 отключит стабилизацию Баумгарте. Установка в значение 1.0 разрешит проникновение за один шаг моделирования. Это быстро, но часто нестабильно.

Столкновения призраков

Jolt использует два метода для смягчения фантомных столкновений, то есть столкновений с внутренними краями фигур/тел, которые приводят к появлению нормалей столкновений, противоположных направлению движения.

Первый метод, называемый "обнаружением активных рёбер", помечает рёбра треугольников в ConcavePolygonShape3D или HeightMapShape3D как "активные" или "неактивные" в зависимости от угла к соседнему треугольнику. При столкновении с неактивным ребром нормаль столкновения заменяется нормалью треугольника, чтобы уменьшить эффект фантомных столкновений.

Порог угла для этого обнаружения активного края настраивается через настройки проекта Physics >Jolt Physics 3D > Collisions > Active Edge Threshold.

Вторая технология, называемая "улучшенным удалением внутренних рёбер", вместо этого добавляет проверки во время выполнения для определения активности или неактивности ребра на основе точек контакта двух тел. Преимущество этого подхода заключается в том, что он применим не только к столкновениям с ConcavePolygonShape3D и HeightMapShape3D, но и к рёбрам между любыми фигурами внутри одного тела.

Расширенное удаление внутренних ребер можно включать и выключать для различных контекстов, к которым оно применяется, с помощью Physics >Jolt Physics 3D > Simulation > Use Enhanced Internal Edge Removal, настроек проекта и аналогичных настроек для queries и motion queries.

Обратите внимание, что ни активное обнаружение ребер, ни улучшенное удаление внутренних ребер не применяются при наличии фиктивных столкновений между двумя разными телами.

Использование памяти

Jolt использует стековый распределитель для временного выделения памяти на этапе моделирования. Этот стековый распределитель требует предварительного выделения определённого объёма памяти, который можно настроить с помощью параметра проекта Physics > Jolt Physics 3D > Limits > Temporary Memory Buffer Size.

Индекс лица с помощью Ray-cast

Свойство face_index, возвращаемое в результатах intersect_ray() и RayCast3D, по умолчанию всегда будет равно -1 в Jolt. Настройка проекта Physics > Jolt Physics 3D > Queries > Enable Ray Cast Face Index включает их.

Обратите внимание, что включение этого параметра увеличит требования к памяти ConcavePolygonShape3D примерно на 25%.

Кинематические контакты RigidBody3D

При использовании Jolt, объект RigidBody3D, замороженный с помощью FREEZE_MODE_KINEMATIC, по умолчанию не будет сообщать о контактах при столкновениях с другими статическими/кинематическими телами из соображений производительности, даже если задано ненулевое значение max_contacts_reported. Если у вас много/больших кинематических тел, перекрывающихся со сложной статической геометрией, например ConcavePolygonShape3D или HeightMapShape3D, вы можете впустую тратить значительную часть ресурсов процессора и памяти, не осознавая этого.

По этой причине данное поведение включается через настройки проекта Physics > Jolt Physics 3D > Simulation > Generate All Kinematic Contacts.

Контактные импульсы

Из-за внутренних ограничений Jolt контактные импульсы, получаемые методом PhysicsDirectBodyState3D.get_contact_impulse(), оцениваются заранее на основе таких факторов, как контактное многообразие и скорости сталкивающихся тел. Это означает, что полученные импульсы будут точными только в тех случаях, когда два рассматриваемых тела не сталкиваются друг с другом.

Area3D и SoftBody3D

Jolt does not currently support any interactions between SoftBody3D and Area3D, such as the wind and gravity properties found on Area3D.

WorldBoundaryShape3D

WorldBoundaryShape3D, представляющий бесконечную плоскость, реализован в Jolt несколько иначе, чем в Godot Physics. В обоих движках есть верхний предел эффективного размера этой плоскости, но в Jolt этот размер значительно меньше, чтобы избежать проблем с точностью.

Вы можете настроить этот размер с помощью настройки проекта :Physics > Jolt Physics 3D > Limits > World Boundary Shape Size.

Заметные отличия от расширения Godot Jolt

Хотя встроенный модуль Jolt по сути является прямой копией расширения Godot Jolt, есть несколько отличий.

Настройки проекта

Все настройки проекта перенесены из категории physics/jolt_3d в physics/jolt_physics_3d.

Кроме того, были переименованы и переработаны отдельные настройки проекта. В частности:

  • sleep/enabled теперь называется simulation/allow_sleep.

  • sleep/velocity_threshold теперь называется simulation/sleep_velocity_threshold.

  • sleep/time_threshold теперь называется simulation/sleep_time_threshold.

  • collisions/use_shape_margins теперь называется collisions/collision_margin_fraction, где значение 0 эквивалентно отключению.

  • collisions/use_enhanced_internal_edge_removal теперь называется simulation/use_enhanced_internal_edge_removal.

  • collisions/areas_detect_static_bodies теперь называется simulation/areas_detect_static_bodies.

  • collisions/report_all_kinematic_contacts теперь называется simulation/generate_all_kinematic_contacts.

  • collisions/soft_body_point_margin сейчас simulation/soft_body_point_radius.

  • collisions/body_pair_cache_enabled сейчас simulation/body_pair_contact_cache_enabled.

  • collisions/body_pair_cache_distance_threshold сейчас simulation/body_pair_contact_cache_distance_threshold.

  • collisions/body_pair_cache_angle_threshold сейчас simulation/body_pair_contact_cache_angle_threshold.

  • continuous_cd/movement_threshold сейчас simulation/continuous_cd_movement_threshold, но выражено в виде дроби, а не процента.

  • continuous_cd/max_penetration сейчас simulation/continuous_cd_max_penetration, но выражено в виде дроби, а не процента.

  • kinematics/use_enhanced_internal_edge_removal сейчас motion_queries/use_enhanced_internal_edge_removal.

  • kinematics/recovery_iterations сейчас motion_queries/recovery_iterations, но выражено в виде дроби, а не процента.

  • kinematics/recovery_amount сейчас motion_queries/recovery_amount.

  • queries/use_legacy_ray_casting был удален.

  • solver/position_iterations сейчас simulation/position_steps.

  • solver/velocity_iterations сейчас simulation/velocity_steps.

  • solver/position_correction сейчас simulation/baumgarte_stabilization_factor, но выражено в виде дроби, а не процента.

  • solver/active_edge_threshold сейчас collisions/active_edge_threshold.

  • solver/bounce_velocity_threshold сейчас simulation/bounce_velocity_threshold.

  • solver/contact_speculative_distance сейчас simulation/speculative_contact_distance.

  • solver/contact_allowed_penetration сейчас simulation/penetration_slop.

  • limits/max_angular_velocity теперь хранится в радианах.

  • limits/max_temporary_memory сейчас limits/temporary_memory_buffer_size.

Узлы Суставов

Соединительные узлы, представленные в расширении Godot Jolt (JoltPinJoint3D, JoltHingeJoint3D, JoltSliderJoint3D, JoltConeTwistJoint3D и JoltGeneric6DOFJoint), не включены в модуль Jolt.

Безопасность потока

В отличие от расширения Godot Jolt, модуль Jolt поддерживает потоко-безопасность, включая настройку проекта Physics > 3D > Run On Separate Thread. Однако эта функция не была тщательно протестирована, поэтому её следует считать экспериментальной.