Физика: поднят предел скорости Rapier — физган больше не отстаёт
Some checks are pending
CI / checks (push) Waiting to run

Корень отставания пропа найден замером и подтверждён на чистом Rapier:
в rapier 0.36 по умолчанию `normalized_max_linear_velocity = 400`, и любая
заданная скорость выше 400 обрезается на шаге. Отсюда 1200 -> 400 и «проп
плетётся за игроком»: никакая пружина не помогала.

- PhysicsWorld::new поднимает `normalized_max_linear_velocity` до 100k
  (в Source скорости выше: бег 650, физган до 5000, падения — тысячи);
  защита от нефинитных значений остаётся;
- тест-страж body_with_set_velocity_actually_moves: тело с 1200 обязано
  проехать >1000 за секунду (до фикса — 400, тест падал);
- временный телепорт-костыль был откачен ранее; трение на удержании
  выключается (combine rule Min), на отпускании возвращается 0.6.

Проверено: 29 сьютов зелёные (включая новый тест скорости).
This commit is contained in:
Niko Marmeladkov 2026-10-24 22:07:29 +03:00
parent 07bc51e332
commit 4a8e75635e

View file

@ -190,6 +190,13 @@ impl PhysicsWorld {
// По умолчанию Rapier ставит Y-вертикаль и −9.81 — у нас Z-вертикаль
// и другие единицы, поэтому гравитацию задаём явно.
world.gravity = Vector::new(0.0, 0.0, DEFAULT_GRAVITY);
// Rapier 0.36 по умолчанию ограничивает скорость 400 единицами
// (`normalized_max_linear_velocity`). В Source скорости выше: бег 650,
// физган до 5000, падения — тысячи. С этим пределом тело с заданной
// скоростью 1200 реально ехало 400 (замер), из-за чего физган не мог
// догнать игрока. Поднимаем предел до 100k, сохраняя защиту от
// нефинитных величин.
world.integration_parameters.normalized_max_linear_velocity = 100_000.0;
Self {
world,
handles: Vec::new(),
@ -1195,12 +1202,9 @@ mod tests {
/// скорость 1200 по X. За секунду тело обязано проехать ~1200 юнитов.
/// Если проезжает меньше — его тормозит контакт/трение, и никакая
/// пружина физгана не поможет (нужно другое решение).
// ОТКРЫТЫЙ БАГ (физган): шаг физики гасит заданную скорость ровно втрое
// (1200 -> 400) даже без пола, контактов, трения (combine rule Min),
// гравитации (gravity_scale 0) и damping (0.000). Именно поэтому проп
// отстаёт от игрока при любой пружине. Тест-страдалец: раскомментировать
// assert после починки.
#[ignore = "открытый баг: шаг физики делит скорость на 3"]
// Причина отставания пропа (найдена этим тестом): в Rapier 0.36
// `normalized_max_linear_velocity` по умолчанию 400, и заданная скорость
// 1200 превращалась в 400. Теперь предел поднят в `PhysicsWorld::new`.
#[test]
fn body_with_set_velocity_actually_moves() {
let mut physics = PhysicsWorld::new();
@ -1239,8 +1243,10 @@ mod tests {
"проехало за секунду при 1200: {moved:.1}, скорость после шага: {:.1}",
v.length()
);
eprintln!("тест-страж: ожидание >1000, факт {moved:.1}");
// assert!(moved > 1000.0, ...); // включить после починки шага физики
assert!(
moved > 1000.0,
"тело проехало только {moved:.1} из 1200 — предел скорости Rapier не поднят"
);
}
/// Проп должен падать и останавливаться на полу, а не проваливаться.