From e6d7454a6a9d71adfe7cb3e6d2178d39dbacbc5d Mon Sep 17 00:00:00 2001 From: Niko Marmeladkov Date: Tue, 13 Oct 2026 14:44:45 +0300 Subject: [PATCH] =?UTF-8?q?engine:=20=D1=82=D0=B5=D1=81=D1=82=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BF=D1=80=D0=BE=D1=88=D0=B8=D0=B2=D0=BA=D1=83=20?= =?UTF-8?q?=D1=82=D0=BE=D0=BD=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D0=B0=20=E2=80=94=20=D0=B3=D0=B8=D0=BF=D0=BE=D1=82=D0=B5=D0=B7?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=B4=D1=82=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B4=D0=B8=D0=BB=D0=B0=D1=81=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Две версии про проваливание проверены тестами и обе оказались неверными. 1. «Пропов нет в коллизии игрока» — пробел реальный и устранён, но игрок ходил по брашам, это его не объясняло. 2. «На низком FPS шаг подшага прошивает пол» — опровергнуто: при terminal-скорости 2000 юнитов/с и dt = 1/60 игрок садится на площадку толщиной 4 юнита, on_ground = true. Тест оставлен как регрессионный сторож: если подшаги когда-нибудь ослабнут, он сразу это покажет. Замер: стояние на спавне gm_construct стабильно 180 кадров (z = -143.9, on_ground = true). Дефект локальный и требует указания места. Причина не найдена — фиксирую это в docs/PARITY.md B3, а не подгоняю тест под желаемый результат. --- crates/engine/src/player.rs | 46 +++++++++++++++++++++++++++++++++++++ docs/PARITY.md | 29 +++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/crates/engine/src/player.rs b/crates/engine/src/player.rs index 664fa2f..da6fc5b 100644 --- a/crates/engine/src/player.rs +++ b/crates/engine/src/player.rs @@ -1265,4 +1265,50 @@ mod tests { player.position.x ); } + + /// Падающий игрок не должен прошивать тонкий пол даже на 60 fps. + /// + /// Скорость падения ограничена 2000 юнитов/с; при dt = 1/60 это 33 юнита + /// за кадр. Число подшагов ограничено восемью, значит на шаг приходится + /// около 6.6 юнита — пол тоньше этого игрок проходит насквозь. Именно + /// это и выглядит как «проваливаюсь при хождении»: чем быстрее кадр, + /// тем больше шаг подшага. + #[test] + fn fast_fall_does_not_tunnel_thin_floor() { + let mut collision = Collision { + brushes: Vec::new(), + tris: Vec::new(), + grid: HashMap::new(), + boxes: Vec::new(), + box_grid: HashMap::new(), + }; + // Тонкая площадка толщиной 4 юнита — как отступы и площадки на картах. + collision.brushes = vec![Brush { + planes: vec![ + (Vec3::new(1.0, 0.0, 0.0), 512.0), + (Vec3::new(-1.0, 0.0, 0.0), 512.0), + (Vec3::new(0.0, 1.0, 0.0), 512.0), + (Vec3::new(0.0, -1.0, 0.0), 512.0), + (Vec3::new(0.0, 0.0, 1.0), 0.0), + (Vec3::new(0.0, 0.0, -1.0), 4.0), + ], + }]; + + let mut player = Player::new(Vec3::new(0.0, 0.0, 400.0)); + // Падаем до удара: за один кадр игрок проходит лишь ~33 юнита, до + // пола от 400 нужно десятки кадров. + for _ in 0..200 { + player.update(&collision, 0.0, 0.0, false, false, 0.0, 1.0 / 60.0); + assert!( + player.position.z >= -1.0, + "игрок не должен пройти сквозь пол, z={}", + player.position.z + ); + } + assert!( + player.on_ground, + "после удара игрок должен стоять на полу, z={}", + player.position.z + ); + } } diff --git a/docs/PARITY.md b/docs/PARITY.md index a63497c..24ff098 100644 --- a/docs/PARITY.md +++ b/docs/PARITY.md @@ -693,3 +693,32 @@ API. Частоты по числу вхождений: - Оси соединения задаются в мировых координатах, как в GMod. - Ограничение угла переводится в радианы; вырожденный диапазон игнорируется. - `pulley` и `thruster` — это не суставы: тяга делается через `add_force`. + +## Часть B3. Проваливание сквозь пол: что проверено и что нет + +### B3.1. Две гипотезы, обе опровергнуты измерением + +1. **«Пропов нет в коллизии игрока».** Гипотеза была верной *как диагноз*, + но не как объяснение жалобы: игрок ходил по брашам. Пробел устранён + (`Collision::boxes`), проп теперь стоит под ногами — это нужно в любом + случае, но от проваливания по брашам не избавило. +2. **«На низком FPS шаг подшага прошивает пол».** Опровергнуто тестом + `fast_fall_does_not_tunnel_thin_floor`: при terminal-скорости 2000 + юнитов/с и dt = 1/60 игрок садится на площадку толщиной **4 юнита** и + `on_ground = true`. Подшагов восемь хватает. + +Обе версии выглядели правдоподобно и обе были неверны — характерная черта +дефектов, которые видны только после попытки воспроизвести их тестом. + +### B3.2. Что измерено + +- Стояние на спавне gm_construct: 180 кадров, `z = -143.9` стабильно, + `on_ground = true`, провала нет. +- Значит дефект локальный и воспроизводится на определённой геометрии. + +### B3.3. Что нужно, чтобы найти причину + +Точное место и обстоятельства: с какой высоты, после какого движения +(прыжок, спуск по рампе, спуск с края) и на каком участке. Без этого +пришлось бы перебирать геометрию карты наугад — а это ровно тот способ, +которым эти две гипотезы и были порождены.