跳轉到

D-20261026-02|hard CCD 持續接觸改掃核心球

2026-10-27 關聯追補:「動態目標只掃核心球」由 D-20261027-02 修訂:持續接觸規則只套用固定目標, kinematic/dynamic 目標照父代以完整形狀求 TOI(ccd_persistent_contact_policy 新值 2)。同代的 D-20261027-01 比照本決策的共識設定模式,新增接觸 normal 求解順序設定。

背景與驅動力

D-20260814-07 讓所有 gameplay dynamic body 固定啟用 hard CCD (PHYSICS_CCD_MAX_SUBSTEPS=2),用來防止高速物體穿過零厚度 trimesh。實際運作時,vendored Rapier 會把每個 夠快的 dynamic body 都當成 CCD 起點,對所有候選 pair 求最早撞擊時刻,再把這一步的位移截斷在該時刻。 這個流程不區分「已經貼在一起」的 pair(issue 001050):

  • 車速被截:輪胎本來就壓在地上,往前滾時預測位置會再往下一點點,幾乎每一步都被判為撞到地面。 正式設定下 61–92% 的幀位移不到「速度 × dt」的 0.8 倍。合成車指令 2.5 m/s,實際只有 1.69 m/s; 八車 10 秒只前進 2.7–2.8 m。
  • 軌跡混沌:截不截斷取決於微米級的狀態差,單幀可從 56 µm 跳到 20.7 mm。任何軌跡類品質閘在正式設定下 只能量到事件前的自由段(D-20261021-01 的已知限制、 001051、001081 的 C 弧牆判準因此無法成立)。
  • 成本:CCD TOI 掃掠占原生 step 的 45–65%(001074 v8 量測)。
  • 同族現象:heavy 起跑出現的「輪地接觸單幀衝量爆衝、掉頭逆行」被研判與此同族(2026-10-26 胎 Hub 研究), 但尚未證實。

逐剛體 enableCcd(false) 無效(ccd_enabled 只決定掃掠範圍,不決定是否為起點),只有世界 CCD substeps 設 0 才會消失;但設 0 會讓高速物體穿牆。

研究原型 v15640 比較了五種模式。2026-10-26 另以 UGC 造型專項驗證在現行 source-kit 上比較 F(現行)、M4、N、 C、T、TC、TM 七種變體,涵蓋非圓輪、持續觸地武器與底盤、薄刀片、車對車與彈對車、piece group 同組牆,以及 公版三場地八車真實情境。

考慮過的選項

  • 維持現狀:車速低於指令、軌跡對微擾極敏感、品質閘沒有鑑別力、成本偏高。正式比賽中,八車 10 秒前進不到 3 m。否決。
  • 全域 CCD substeps 設 0:截斷完全消失,視界與模式 4 逐格相同。但穿牆守門 15 案中有 8 案會穿 (60/120 m/s 撞直牆、貼外牆進弧三速全穿),違反 D-20260814-07 的前提。否決。
  • 逐剛體停用 CCD(例如輪胎不啟用):實測與正式設定逐位元相同,在現行 kernel 下無效。若要生效,得改 kernel 讓 ccd_enabled 決定「是否為起點」;但這樣輪胎就完全沒有 CCD,高速撞牆時要靠其他剛體擋,而且輪胎本身也是會 高速撞牆的物體。否決。
  • CCD substeps 改 1 或 4、soft CCD 預測距離大於 0:只改截斷的次數或時機,不改「貼著就被截」的機制; soft CCD 是提前接觸的預測約束,D-20260814-07 已說明它不能取代 hard CCD。不單獨採用。
  • 模式 1:持續接觸的 pair 整個跳過 TOI:地面接縫仍會截斷;120 m/s 進弧時穿牆。否決。
  • 模式 2:模式 1 再加上同 piece group 相鄰塊:地面接縫不再截斷,但從 30 m/s 起,貼外牆進同組弧段會穿過 0.1 m 牆盒,深 8–48 m。否決。
  • 模式 3:持續接觸的 pair 改掃核心球,不含 piece group:地面接縫仍會截斷,C/D 九格全紅(yaw 3–15°)。否決。
  • 模式 4(M4):持續接觸(含同 piece group 相鄰塊)改掃剛體質心核心球:單一樣本守門 15 案全擋, 但起點微擾 7×15=105 次集合中有 2 次真穿過。另有兩個實證缺陷:
  • 薄件貼地 piece 時,同組牆 piece 也被當成持續接觸,只掃核心球,刀片平躺衝牆在 30/60/120 m/s 越牆 0.42/8.1/25.6 m;
  • 凸包 ccd_thickness 取局部 AABB 最小半寬,斜放薄 hull 被高估(6.2 mm 對實際 0.5 mm),核心球外凸, 貼地每幀被截斷,起始重疊時保護也失效。 否決。
  • N:只有 tire/roller 滾動 cylinder 對場地放寬:安全性與現行相同,但非圓 UGC 輪(方、六角、星、釘) 仍被截斷 24–36%,對作者不公平;kernel 也分不出胎與 rotor 武器、場地轉盤的 cylinder,需要額外的逐 collider 共識位元。否決。
  • C:以接觸 collider 中心、該 collider 自身厚度的核心球:核心較大時,已穿入數 mm 的物體在步首與下一段牆 重疊而被忽略,105 次集合有 3 次真穿過。否決。
  • T/TC:持續接觸 pair 先以完整形狀求 TOI,命中異面才接受:安全,但核心尺寸未處理斜放薄 hull。 由 TM 取代。
  • TM:異面判定+形狀質心核心球(半徑取厚度與內切半徑的較小者):採納。
  • 異面門檻與核心比例提升為 protocol 常數:可治理調整會讓 kernel 行為隨設定漂移,且這三個值只在 kernel 內部有意義。否決,固定在 kernel 內。
  • 與摩擦切向基底修正(001075)合併成一代:兩者都改變全部軌跡,合併後無法分辨各自的效果。否決,分兩代, 本決策先做;數值重校等兩者都落地後一次進行。
  • 另案方向(不屬本決策):ccd_thickness 只取滾動面、不接觸的內件不參與 CCD——已由 D-20261026-01 以「被包覆內件不建 collider」達成; 摩擦切向基底改圓錐投影或對齊滑移(001075)處理的是偏航,不處理截斷。

決定

  • 持續接觸:在步首(或 CCD 子步首),narrow phase 中(來源 collider, 目標 collider)pair 有 manifold 點, 且 dist ≤ prediction_distance,即為持續接觸。現行 bounded profile 的 prediction_distance 為 0.002 m (normalized 0.002 × length_unit 1)。下列情況也算:來源與同一固定剛體、同一非零 piece group 的任一 piece 持續接觸。判定只讀上一步已決定的 manifold,是布林值,與走訪順序無關。
  • 固定目標(TM):持續接觸 pair 先以完整形狀求 TOI。
  • 在命中位置以接觸查詢(容差=prediction_distance+4×allowed linear error)取命中點法線;與持續接觸 參考法線(步首最深接觸點的法線)夾角 ≥ 30° 時,視為異面(例如同組的牆),接受完整命中並照常截斷。
  • 命中同一面或查詢無結果時,改掃核心球。
  • 完整形狀未命中時,仍掃核心球。
  • 動態目標:持續接觸 pair 只掃核心球(車對車、彈對車)。
  • 核心球:球心在該 collider 的形狀質心(不是剛體質心);半徑= min(CORE_FRACTION × shape.ccd_thickness, CORE_INSCRIBED_FRACTION × 內切半徑),CORE_FRACTION = 0.25、 CORE_INSCRIBED_FRACTION = 0.5,內切半徑為形狀質心到形狀邊界的最短距離。凸包的 ccd_thickness 是局部 AABB 最小半寬,斜放的薄 hull 會被高估,所以必須同時以內切半徑限制。
  • 複合或 trimesh 目標沿用既有的子形狀掃掠路徑;support-map 目標以 Ball 對該形狀掃掠。
  • 感測器與偽 pair 不變。
  • 非持續接觸的 pair 不變,照舊以完整形狀求 TOI。
  • 常數位置:30°(kernel 以餘弦 0.866 比較)與兩個核心比例都是 kernel 內固定常數,由 physics-version 釘住;不開放治理調整。
  • 共識設定:以 world 的不可變整合參數 ccd_persistent_contact_policy(0=完整形狀、1=本決策)承載, 由 physics-version-pinned protocol 常數 PHYSICS_CCD_PERSISTENT_CONTACT_POLICY = 1 指定,在 bounded profile 之後回填。
  • 不得使用 thread-local 或任何不進快照的狀態。
  • snapshot、immutable world config 與 restore 都要驗證此設定,有差異就原子拒絕。
  • 不變:PHYSICS_HARD_CCD_ENABLED=true、PHYSICS_CCD_MAX_SUBSTEPS=2、PHYSICS_SOFT_CCD_PREDICTION_M=0; dynamic body factory 與「不得依速度切換 CCD」都不變。
  • 穿入上界:核心球擋的是「穿過」,不是「穿入」。只掃核心球時,穿入上界=核心中心沿法線到形狀表面的 距離 − 核心半徑,可能接近外接半徑。實測:下壓 ≤ 4.7 mm、非圓輪稜角 ≤ 8.4 mm、尖刺頂薄板 9–13 mm(疑似, 量法分不出穿過與越頂)。canon 明文記載。
  • 正式品質閘:
  • 穿牆守門 15 案以起點微擾 7×15=105 次集合執行,判準為 0 次真穿過(牆頂以下);越牆彈飛另記為既有 現象(現行 F 2/105)。
  • 同組牆+薄刀片平躺衝牆、斜放薄 hull 貼地截斷、非圓輪截斷率與車速、武器與底盤落地及下壓沉入、 快照還原後的第一步與未中斷執行一致。
  • vendor:建立新的 repair 代(父代為 001038 piece-group 代,其父 repair15639)並重建 wasm。旗標關閉時, 步進軌跡與父代逐位元相同(有限等價);快照位元組只差新增的設定欄位。
  • 001049 併入同一代:piece-group leader 換手的 warm start 近似一併修正(反序時切向 world 衝量取反號、 solver 力臂對調;被 broad phase 移除的 leader 的 cluster 在同一步交給新 leader)。
  • 上線前必做。pinning 的 vendored 版本值同步需另行取得同意(001057)。

後果與影響

  • 玩家可見:
  • 車速回到指令值。公版三場地八車 600 幀:截斷 28%/99.6%/99.5% → ≤ 0.4%,車速 2.20/0.32/0.34 → 2.50/2.60/2.23 m/s;與場地最大穿入 ≤ 2.8 mm。
  • 車真的會開進彎、互撞、貼牆,碰撞事件與 bounded-step 拒絕都會變多。
  • 非圓 UGC 輪仍有 12–23% 截斷(輪子離開 2 mm 預測帶後再落下屬真碰撞),稜角沉入 3–8 mm。
  • 偏航不會因此改善(001072、001075 另案)。
  • 掉頭與衝量爆衝是否改善,要在正式化後量測,不在本決策的保證內。
  • 決定性:軌跡全部改變。研究證據:模式 0 與正式釘版 SDK 逐位元相同;原生 728 run 兩次 hash 全同; 串行與 7 thread 並行 504 hash 全同;wasm 單跑與並行相同;八車每格兩重播全同。
  • determinism golden 升 revision(canonical-two-car-revision-18)。
  • conformance physics/track-entity-snapshot 的 snapshotSha256 會改,其餘欄位依實跑結果更新。
  • Node 與 Chromium 核對後,再依 CI 矩陣跑 Firefox、WebKit 與其他 OS。
  • 版本:wasm digest 與 RAPIER_VERSION_CURRENT 更換;版本字串長度仍在 128 bytes 上限內。 pinning 的 vendored 版本值需另行同步(001057)。
  • 資產:PhysicsManifest 沒有 CCD 欄位,公版零件與場地 bytes、manifest digest 都不變。
  • 品質閘與預算:
  • track-collision-gates 的視界會覆蓋事件後(原型 +18~+235 幀),軌跡判準第一次真正有鑑別力。 B 45° 前提窗要改治具;D 沿格線穿入(分段與單顆同為 2.29 mm)要裁決判準。 A 10°、A 牆端、C 弧牆的 yaw 差交給 001051 歸因。001081 的 C 弧牆改用固定 2 cm/1° 絕對判準重跑。
  • hard-ccd-performance 與 track-pieces-performance 的預算要用真實賽況重訂。公版八車 600 幀 step (P50/P95 ms,node,計時噪音 ±10–15%):snowy F 22.2/72.0 → TM 19.7/50.1;urban 32.0/39.4 → 32.2/99.4; jungle 47.1/54.3 → 33.1/84.5。F 在 urban/jungle 的 P95 偏低是因為車幾乎沒動;TM 比 M4 慢約 10–50% (持續接觸 pair 多一次完整形狀掃掠)。
  • piece group 現況:分組鍵是「材質+來源節點」,未宣告 wall_strip 的節點一律按 8 m 格切成地面。urban 的 Building_01–23 與 jungle 的 Cliff_Stones 因此同一組內同時含朝上平面與陡面。TM 的異面規則要求牆與地面是不同 collider;同一顆 piece 內同時有地面與牆三角時,接觸查詢可能回傳地面法線,風險會回來(未實測)。由另案處理 (地面切格節點含陡面時切開,或編輯器驗證警告)。
  • 既有缺陷(不屬本決策):動態薄目標(2 mm 護板、彈頂車側護板)在現行 F 下也會被穿過;小物體高速進弧越牆 彈飛在 F 也有 2/105。另案處理。
  • 數值重校:馬達、熱、磨耗等 playtest 數值是在車速被截的條件下觀察的,要重新校準。 等 001075 也落地後一併進行。
  • pre_launch:直接更新當前基線,不保留舊核心的相容、遷移或雙讀。
  • canon 同步:
  • 程式架構/physics-engine.md 第 2.2 節:刪除「已知限制」段,寫入持續接觸規則、核心球與穿入上界;
  • 程式參數/protocol.md:新常數;
  • 程式參數/network.md:RAPIER_VERSION_CURRENT;
  • 程式架構/testing.md:golden、digest 與守門;
  • D-20261021-01 中的已知限制由本決策修正。
  • 需補的驗證:
  • kernel 單元測試:parallel feature 實跑、彈丸對車、薄刀片貼牆加速、restore 後第一步與未中斷執行一致;
  • 有限等價(旗標關閉時與父代一致);
  • 守門 15 案入正式閘;
  • 用現行零件(D-20261026-01 之後,ccd_thickness 已改由外圈決定)重量截斷率、車速與守門;
  • 三車三場各 30 起跑的完賽與掉頭統計;
  • 四公版場地的八車成本;
  • 001080 在新核心下重測。