Four things that separate a marble runner that feels good from one that feels off — kinematic bodies driven by setNextKinematicTranslation (not setTranslation), a ray-cast grounded jump that can't be spammed mid-air, an "infinite" level that recycles blocks in place instead of growing an array, and per-frame camera lerp with reused scratch vectors. Straight from the /gamecenter 3D Race source.
Rapier's wasm loader returns a Promise, but a three.js render loop starts on `new`. If you naively `await RAPIER.init()` in the constructor, you get a black screen while wasm downloads. If you fire off `.then(...)` and forget about it, your first ticks crash on `world.step` because the world doesn't exist yet. Tank Battle threads this needle with a `physReady` flag, a purely-cosmetic pre-physics render loop, and a check-and-wait "deploy" gate.
Rapier surfaces contact detection through three interfaces on top of the same underlying check — the raw event queue, R3F's `onCollisionEnter` prop, and sensor colliders with `onIntersectionEnter`. Same feature, three ergonomics, different tradeoffs. This post walks through each shape with real call sites from Tank Battle and 3D Race, and where each one belongs.
3D 弹球赛道是一款arcade类互动游戏。操控一颗由物理引擎驱动的弹珠,在不断回收重组的无尽障碍赛道上前进。通过连续路段会累计距离、分数与连击,撞上移动机关会损失三条生命之一。沿途宝石以及护盾、加速、减速时间等临时增益,会在赛道持续生成时形成短暂的策略窗口。每次重新开始都会回到三条生命,但已获得的金币和最高分仍会保留。