Использование физики Jolt
Введение
Физический движок Jolt был добавлен в качестве альтернативы существующему физическому движку Godot Physics в версии 4.4. Jolt разработан Йорритом Роуве с упором на игры и VR-приложения. Ранее он был доступен в качестве расширения, но теперь встроен в Godot.
Важно отметить, что встроенный модуль Jolt Physics считается незаконченным, экспериментальным и не имеет функционального соответствия ни с Godot Physics, ни с расширением Godot Jolt. Поведение модуля может измениться по мере его дальнейшей разработки. Пожалуйста, учитывайте это при выборе модуля для своего проекта.
Существующее расширение теперь находится в режиме обслуживания. Это означает, что исправления ошибок будут объединены, и оно будет совместимо с новыми версиями Godot до тех пор, пока встроенный модуль не достигнет функционального паритета с расширением. Расширение можно найти здесь, на GitHub <https://github.com/godot-jolt/godot-jolt>`_, и в библиотеке ресурсов Godot.
Чтобы изменить 3D-физический движок на Jolt Physics, установите для параметра Project Settings > Physics > 3D > Physics Engine значение Jolt Physics. После этого нажмите кнопку Save & Restart. После повторного открытия редактора 3D-сцены должны использовать Jolt для физики.
Заметные отличия от Физики Годо
Между существующим движком Godot Physics и Jolt существует множество различий.
Совместная собственность
Текущие интерфейсы узлов 3D-сочленений не совсем соответствуют интерфейсу собственных сочленений Jolt. В связи с этим ряд свойств сочленений не поддерживаются, в основном те, которые связаны с настройкой мягких пределов сочленений.
Неподдерживаемые свойства:
PinJoint3D:
bias,damping,impulse_clampHingeJoint3D:
bias,softness,relaxationSliderJoint3D:
angular_\*,\*_limit/softness,\*_limit/restitution,\*_limit/dampingConeTwistJoint3D:
bias,relaxation,softnessGeneric6DOFJoint3D:
*_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 не поддерживает никаких взаимодействий между SoftBody3D и Area3D, таких как события перекрытия или свойства ветра, найденные в 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. Однако эта функция не была тщательно протестирована, поэтому её следует считать экспериментальной.