torqueCars
Drivable cars that behave like machines, as one family switched by one setting. Twelve kinds in three looks, each with its own engine character, gearing and drive layout, and every part swappable while you drive. Built on the engine's own vehicle physics: `WheelCollider` tyres th…
torqueCars
Drivable cars that behave like machines, as one family switched by one setting.
Twelve kinds in three looks, each with its own engine character, gearing and
drive layout, and every part swappable while you drive. Built on the engine's
own vehicle physics: WheelCollider tyres that spin and slip, a ShaftNetwork
drivetrain (engine torque curve → clutch → gearbox → differentials → wheels)
solved inside the physics step, and a SoftBody shell that crumples where it is
hit and stays crumpled until the car is reset.
First example
Install torqueCars (it brings driveSurfaces for ground grip when you install
that too). Then, with the world in play, run this from the console
(execute) — or paste it into your scene's entrypoint.luau inside
function onLoad() ... end:
local Assemble = require("torqueCars.assemble")
local car = Assemble.spawn({ kind = "rally", position = vector.create(0, 0.2, 6) })
-- W/S throttle and brake (S at a stop reverses), A/D steer, Space brake,
-- Ctrl handbrake, E/Q shift, M auto/manual, R reset, Backspace respawn.
The car takes the player's driving controls at once (gamepad and touch too).
To make a car each joining player's own body, build it under the scene's
player prototype in build.luau:
local Assemble = require("torqueCars.assemble")
local body = entity.spawn("body", { parent = prototype })
Assemble.build(body, { kind = "coupe", look = "real" })
body.component.add("Car", { kind = "coupe", look = "real", control = "player" })
prototype.component.add("PlayerPrototype", { body = body, camera = rig })
Add a Garage component to any scene entity and G opens the parts panel.
The family: one setting each
Every field below is on the Car component and can be changed live (from the
garage, from code with car:setPart(slot, name), or in the inspector):
| field | values |
|---|---|
kind | hatchback coupe muscle rally drift pickup van suv buggy kart boxtruck electric |
look | lowpoly toy real |
paint | white red orange yellow green blue purple black silver teal pink brown (empty = the kind's) |
engine | i4 turbo4 v6 v8 v12 diesel rotary electric kart |
gearbox | manual5 manual6 auto sequential direct |
diff | open lsd locked |
tyres | road sport slick drift offroad snow studded steel |
control | player script (AI / code via setIntent) none |
autoShift, assists | auto gear changes; ABS + traction control |
An empty part name means "the kind's own". All data is in torqueCars.catalog.
Measured 0–100 km/h (stock, flat tarmac, assists on, simulated time)
All twelve measured together on a 2 km tarmac strip with Bench.accelerate, full-rate controller.
| kind | layout · engine · gearbox | 0–100 | real class |
|---|---|---|---|
| hatchback | FWD · 1.6 four 122 hp · 5-sp manual | 10.9 s | 9–11 s |
| coupe | RWD · 3.5 V6 330 hp · 6-sp manual · LSD | 6.9 s | 5–6 s |
| muscle | RWD · 6.2 V8 455 hp · 6-sp manual · LSD | 7.0 s | 4.5–5.5 s |
| rally | AWD · 2.0 turbo four 300 hp · sequential | 5.2 s | 4–5 s |
| drift | RWD · twin-rotor 240 hp · 5-sp · welded diff | 7.2 s | 5.5–6.5 s |
| pickup | RWD · 6.2 V8 · 6-sp automatic | 8.6 s | 6.5–8 s |
| van | FWD · 2.5 turbo-diesel 180 hp · 5-sp | 14.1 s | 11–14 s |
| suv | AWD · 3.5 V6 · automatic | 7.4 s | 7–8.5 s |
| buggy | RWD · 1.6 four · sequential · locked | 8.1 s | 6–7 s |
| kart | RWD solid axle · 125cc 45 hp two-stroke · sequential | 7.7 s | 4–5 s |
| boxtruck | RWD · diesel · automatic, 5.2 t | never: governed at 93 km/h (0–80 in 20.1 s) | 30–45 s |
| electric | AWD · 300 kW dual motor · single speed | 4.3 s | 3.5–4.5 s |
Measure your own with torqueCars.bench (Bench.accelerate(car, 100),
Bench.brake(car, 60), Bench.brakeRolling(car, 60)); the bench turns the car's lod off.
The powerful rear-drivers (muscle, coupe) and the kart are traction-limited off the line:
traction control holds the driven tyres near their peak slip, and with it off they spin
without limit (#20654), so they launch slower than their real twins.
Measured 60–0 km/h braking (stock hatchback, road tyres, ABS, rolling start)
| tarmac | concrete | sand | cobbles | gravel | mud | dirt | wet tarmac | grass | snow | ice |
|---|---|---|---|---|---|---|---|---|---|---|
| 17.2 m | 18.4 m | 19.0 m | 20.6 m | 22.0 m | 22.6 m | 23.2 m | 26.3 m | 27.3 m | 33.7 m | 113.8 m |
Gravel stops 28 % later than tarmac, ice 6.6× later. Sand and mud stop shorter than their grip alone suggests because the wheels sink and plough (the surface's bogging drag), as they do in a real car. Studded tyres multiply ice grip 4.2×, snow tyres snow grip 1.9×, off-road tyres loose ground 1.35×.
Measured damage
A rally car driven into the valley's concrete crash wall at 60 km/h (crash detector closing
speed 44–50 km/h, the rest absorbed in the first instants of contact) kept a permanent crush of
9.5 cm nose-first and 12.7 cm side-on, unchanged 5 s later. The dent stays until
reset() or a respawn, which rebuild the shell undamaged. The rigid core spans the cabin (76 %
of the length), so the shell's nose and tail are the crumple zones.
Cost
Per car on a desktop (native, in the editor): the driver runs at the physics tick, about
0.3–0.8 ms a step (network inputs are written only when they change; each
ShaftNetwork:set costs ~0.2 ms), and the soft-body shell ~0.15–0.2 ms a step at
resolution 5 (36–40 particles). Script-driven cars more than 60 m from this peer's own car
run their controller every other step (lod, on by default).
How it drives
- Engine: full-throttle torque curve per engine (idle, redline, limiter); idle governor; turbo spool lag (turbo four, diesel); a rev limiter that cuts fuel in 70 ms bursts. Engine braking from friction and pumping losses.
- Clutch: automatic — slips to launch, opens for every shift, re-engages (manual ≈0.3 s, sequential 80 ms, automatic slurs like a torque converter).
- Gearbox: auto-shift by rpm and pedal (kickdown included) or manual E/Q; holding brake at a standstill selects reverse.
- Differentials: open, limited-slip (preload + bias) or locked; AWD cars add a biased centre diff.
- Tyres: grip curve per tyre set, multiplied by the ground under each wheel
(
driveSurfaces) and the set's affinity for that ground — studded tyres on ice, off-road tyres on gravel. - Body: a plastic soft-body shell held to the chassis along the cabin floor,
so the nose and tail are crumple zones. A 60 km/h wall hit leaves about 10 cm of
permanent crush (9.5 cm measured nose-first, 12.7 cm side-on).
car:reset()(R) repairs it.car.damagecounts from the shell's settled shape, so a fresh or respawned car reads 0 %. - Cockpit: the body draws its inner faces as dark cabin trim and leaves the
glass open from inside, and every car carries a steering wheel in front of its
seat, so a camera at
car.mountSeatsits in a cabin and one atcar.mountHoodlooks over the bonnet. - Respawn:
respawn()(Backspace) takes the car back to where it stood once it had settled after spawning (a spawner that moves the car in its first second moves the spawn point with it), or tosetSpawn's point, set down on the ground there. - Drag: aerodynamic drag, rolling resistance and soft-ground bogging.
Values a car publishes
Gauges, engine sounds, cameras and AI read the car only through named values
on the chassis (car.rpm, car.kmh, car.gear, car.load, …). The full list
and the Car API are in CONTRACT.md in this package.
Contents
Carcomponent — the driver (input or script), drivetrain control, assists, damage, values.Garagecomponent — the live parts panel (G / d-pad up / touch).torqueCars.assemble— builds a car under a chassis entity (build,spawn).torqueCars.catalog— kinds, engines, gearboxes, diffs, tyres, paints.torqueCars.bodies— the 36 body meshes, wheels and paints (three looks).torqueCars.bench— 0–100 and braking measurements.torqueCars.cars— registry of live cars (Cars.all(),Cars.localPlayer()).driveControlsinput map — throttle, steer, brake, handbrake, boost, recover (keyboard, gamepad, touch); the car's own, so it does not depend on the engine's vehicle map.carControlsinput map — shift, auto/manual, respawn, garage (keyboard, gamepad, touch).carGalleryscene — every kind in every look side by side.
Multiplayer
Each car is simulated by the peer that owns it (a player's car by that player, AI cars by
the host); every other peer draws it from the owner's poses. The engine replicates the
soft-body dents from the owner, so everyone sees the same crumpled panels, including a
player who joins later. The values a voice, a gauge or a brake lamp needs (car.rpm,
car.load, car.throttle, car.gear, car.shiftCount, car.boost, car.skid,
car.brake, car.impactCount, …) are declared with a replication rate, so remote cars
sound and light up as they drive. The part fields (kind, engine, tyres, …) are synced:
a swap made in one player's garage reaches every peer. Driving intent and network inputs are
local to the owner. Verified on one machine with the engine's replication read-outs; a
second real client has not been connected yet.
Known engine limits
- #20569 — wheels do not read the ground's named surfaces yet, so each car
ray-casts under its wheels itself and asks
driveSurfacesfor the grip. - #20610 — rolling resistance is in progress in the engine; the car applies
its own rolling resistance and drag as forces and leaves
rollingResistanceoff double-counting. - #20543 — wheels have no volume and cannot come off: a crash dents the body but never knocks a wheel loose, and a wheel can clip through a wall the body stops at.
- #20654 — held at full throttle a wheel can spin up without limit; the rev limiter and traction control (assists) keep it in check, with assists off a stationary burnout can over-spin.
- #21001 — a drivetrain's cost grows quickly with its parts, so every car uses the smallest network for its layout (7 parts FWD/RWD, 9 AWD) and writes network inputs only when they change.
- #21241 / #21242 — synced entity references and lists with gaps do not reach other players; the car keeps none in synced fields (the shell's attachment is re-made on each peer).
Scoped to this part · feeds back into the world's score.