How a car accelerates, corners, settles over bumps and stops. This page owns every physics field: its unit, its accepted range and what changing it actually does. API covers how to read and write these values from a script. Model standard covers measuring a new car in the first place.
Before you change a number
A World Vehicles car is a composite RDR object with custom four-wheel physics. The C# solver calculates suspension and tyre forces, gearing and drag; the RedM bridge reads real body and ground contacts and applies the resulting impulses.
Two consequences worth holding on to:
- A good result in the solver does not prove the asset, the ground probe or the native host is behaving. Check contacts before blaming values.
- Field names from other Cfx platforms and
handling.metado not transfer. The fields below are the entire vocabulary.
Each car keeps its own baseline in its module:
wv_<vehicle>/vehicle.json
profiles
<profileId>
physics
Keys are case-sensitive: EngineTorque, never engineTorque. Values are JSON numbers, never quoted strings. Unknown keys are rejected, so inventing Acceleration or TopSpeedMph creates nothing.
Four scopes, and picking the right one
| Scope | Use it for | Affects | Survives restart |
|---|---|---|---|
| Model baseline | The car's stock definition | That profile wherever it loads | Yes, it is in the module's vehicle.json |
| Model settings | Server-specific stock handling | Every car of that profile, and future spawns | Only if you save it |
| Instance handling | One upgrade or one experiment | A single car | No |
| Global settings | Transmission policy, controls, speedometer, debug | The whole fleet | Only if you save it |
"Global handling" means the shared baseline for one model. It does not mean every car should get the same wheelbase, inertia or suspension.
The in-game /wvmenu panel exposes all four scopes; what it can do and who may open it is in Getting started.
Handling changes need the car assembled and stopped at no more than 0.6 m/s. A model edit needs every car of that profile stopped. A global transmission change needs the whole fleet stopped. Who is allowed to make each change is in the API reference.
Units and axes
| Quantity | Unit |
|---|---|
| Position, radius, suspension length | Metres, model-local X right, Y forward, Z up |
| Wheel order | 0 left front, 1 right front, 2 left rear, 3 right rear |
| Mass | kg |
| Body unit inertia | m², multiply by mass for full rotational inertia |
| Wheel rotational inertia | kg·m² |
| Force, torque | N, N·m |
| Spring, damping | N/m, N·s/m |
| Steering angle and rate | Radians and rad/s |
| Panel and light rotations, heading | Degrees |
| Velocity | m/s; mph = m/s ÷ 0.44704, km/h = m/s × 3.6 |
The steering-in-radians, everything-else-in-degrees split catches people out more than any other convention here.
The whole configuration has to validate together, not just each field:
MinLength < RestLengthandIdleRpm < RedlineRpm.MaxFrameTime >= MaxStep.- Exactly four ordered mounts, at least one driven wheel.
GearRatiosholds 1 to 8 positive entries. The range check does not design a gearbox for you; use a sensibly descending sequence.- Vectors are exactly three finite numbers. No
NaN, no infinity, no numeric strings.
The ranges below are accepted limits, not recommended targets. Your installed build answers authoritatively through getHandlingSchema, which also returns input steps and read-only flags.
Geometry and solver, read-only
These describe the converted body. They are not performance settings, and the editor will not let you change them live.
| Field | Range | Meaning |
|---|---|---|
Mass |
100–50000 kg | The collision body's intended mass. Lightening the number while the asset stays heavy is not a speed fix. |
InertiaX/Y/Z |
0.001–100 m² | Whole-body unit inertia. X mostly pitch, Y roll, Z yaw. |
COM |
±10 m | Real local centre of mass. Dropping it arbitrarily hides bad geometry and creates odd roll. |
Mount0..3 |
±10 m | Suspension top anchors in wheel order. Not tyre contact points. |
WheelRadius |
0.05–2 m | Final tyre radius, shared by the solver. Not a gearing shortcut. |
MaxStep |
0.001–0.02 s | Maximum solver substep. Not an acceleration multiplier. |
MaxFrameTime |
0.001–0.25 s | Long-frame rejection threshold. Raising it to hide stalls costs stability. |
ForceScale |
0.01–10 | Native bridge scale. Not an engine upgrade. |
Changing these means changing the asset. See Model standard.
Suspension
| Field | Range | Effect |
|---|---|---|
SpringStiffness |
100–500000 N/m | Per-wheel spring rate. Too low bottoms out, too high amplifies every bump. |
DamperRate |
0–100000 N·s/m | Base damping. More settles oscillation, too much makes bumps harsh. |
CompressionDampingMultiplier |
0–4 | Damping while the body moves toward the surface. |
ReboundDampingMultiplier |
0–4 | Damping while it moves away. Excess rebound holds the car down through repeated bumps. |
RestLength |
0.01–3 m | Uncompressed suspension length. Raises equilibrium height; it is not ground clearance. |
MinLength |
0–2 m | Fully compressed length. Must stay below rest length. |
FrontAntiRoll |
0–100000 N/m | Front axle roll stiffness. |
RearAntiRoll |
0–100000 N/m | Rear equivalent. Extreme rear stiffness starves the inside wheel. |
MaxWheelLoad |
100–200000 N | Per-wheel support cap. Too low leaves the car unsupported. |
Static compression on level ground works out as:
compression ≈ Mass × 9.81 / (4 × SpringStiffness)
loaded length ≈ max(MinLength, RestLength − compression)
That is a setup estimate, not the exact native equilibrium: weight distribution, geometry, damping and the bridge all still matter. At 1900 kg and 31000 N/m it predicts about 0.15 m of compression.
To raise one car by ten centimetres use setSuspensionHeight with 0.10. It adds to the model baseline rest length, so calling it twice does not add twenty. To change stock ride height for the whole model, edit RestLength.
For a heavier, more planted feel, get clearance and travel right first, then damping, then spring and anti-roll balance, then steering. Do not fake weight by letting the body sink into its own collision.
Tyres and ground contact
| Field | Range | Effect |
|---|---|---|
LongitudinalGrip |
0.05–5 | Peak drive and braking force against supported load. |
LateralGrip |
0.05–5 | Peak cornering force. Very high values make steering abrupt and hide bad balance. |
RollingResistance |
0–1 | Rolling loss. Not a speed governor. |
TireB |
0.01–100 | Slip-curve stiffness: how fast force builds with slip. |
TireC |
0.01–2 | Slip-curve shape. Tune with B and grip together. |
WheelInertia |
0.01–100 kg·m² | Per-wheel rotational inertia. Changes spin-up, not body mass. |
Driven0..3 |
Boolean | Which wheels get torque. Core default is rear drive. |
Capsule |
Boolean | Capsule ground tests instead of rays. Does not create a wheel collider. |
ProbeRadius |
0–2 m | Capsule radius. Large values catch surfaces you did not mean. |
TraceFlags |
0–65535 | RedM shape-test bitmask. Not the drawable IncludeFlags mask. |
ContactTimeout |
0.001–2 s | Maximum age of a ground sample. Extending it keeps stale ground rather than fixing lost contact. |
VisualRange |
1–1000 m | Client visual culling distance. |
The tyre model is peak × sin(C × atan(B × slip)) with a combined longitudinal and lateral friction ellipse. Acceleration and cornering share the same available grip.
Wheel visuals are separate props. A spinning wheel proves nothing about contact, load or torque, so check per-wheel contact flags and normal loads before touching grip. Equally, a working tyre probe is not a body collision test: a car can support itself perfectly while players walk straight through it.
Explicit physics.Capsule, TraceFlags, ProbeRadius, ContactTimeout and VisualRange take precedence over the older probe.* and profile-level fallbacks. Editing the legacy fields does not reach this solver.
Engine, gearbox and brakes
| Field | Range | Effect |
|---|---|---|
EngineTorque |
0–10000 N·m | Peak torque before the RPM curve, ratios and drivetrain loss. Not horsepower. |
IdleRpm |
100–5000 | Lower running bound. |
RedlineRpm |
500–20000 | Upper bound, must exceed idle. Drive cuts near redline. |
GearRatios |
1–8 values, each 0.1–20 | Forward ratios in order. The count is the gear count. |
FinalDrive |
0.1–20 | Multiplies every ratio. Higher means more wheel torque, less speed per RPM. |
ReverseRatio |
0.1–20 | Separate from the forward array. |
DrivetrainEfficiency |
0.01–1 | Fraction of engine output that reaches the wheels. |
MaxSpeedMps |
0–100 m/s | Forward torque-governor target. Zero disables the governor, not gravity. |
BrakeTorque |
0–50000 N·m | Applied to each wheel at full input, not divided among four. |
HandbrakeTorque |
0–50000 N·m | Per rear wheel at full input. |
EngineBrakingTorque |
0–5000 N·m | Extra braking on driven wheels off-throttle with the engine on. |
Torque is shared across the driven wheels. The RPM curve and shift thresholds live in code; there is no JSON torque curve to author.
Shift policy
Automatic upshifts at 85% of redline, downshifts at 30%, with a 0.4 second cooldown. A manual downshift that would over-rev is refused. Swapping between forward and reverse needs both longitudinal and horizontal speed under 0.8 m/s. That policy explains most rejected inputs; sending the same gear change every frame will not get round it.
A target is not a guarantee
| Target | MaxSpeedMps |
km/h |
|---|---|---|
| 80 mph | 35.7632 | 128.75 |
| 160 mph | 71.5264 | 257.50 |
The governor eases drive away over the last 0.5% before the target. It never clamps velocity and never brakes, so a car can pass the target downhill and never reach it uphill.
To sanity-check gearing, the no-slip redline speed in top gear is:
speed_mps = RedlineRpm × 2π × WheelRadius / (60 × last_GearRatio × FinalDrive)
That is an upper bound. Real speed still depends on grip, torque, drag, slope and damage.
The known host ceiling
RedM's native damping imposes a speed ceiling that more torque does not solve. The workaround is a controller setting rather than a physics field, and every use of it re-checks that the body is assembled, that the authored and live model hashes match, and that this client still owns the car. Switches cover the fleet by module group:
| Switch | What it covers |
|---|---|
hostPhysics.pioneerDampingOverride |
The four Pioneer modules |
hostPhysics.*DampingOverride |
Any further module group you install, each with its own switch |
Each one takes a literal boolean, each needs the exact matching wv_<profile>_body model, and each needs a core restart. None of them is a wildcard: a lookalike profile, a clearance test variant or a model with a similar name is not covered, and no switch enables another switch's cars. A shipped production config has them on, because that is the state the prepared fleet was driven in.
Rolling one back means turning the flag off and spawning a fresh car. The native slot has no readback, so a car that already received the treatment is not restored by clearing the flag.
A recorded run reached about 56.83 mph on a mixed route with improved acceleration. That was not a clean top-speed test and says nothing about any other model.
Steering and drag
| Field | Range | Effect |
|---|---|---|
SteeringAngleLimit |
0.01–1 rad | Low-speed lock. 0.5236 rad is 30°. |
SteeringRate |
0.01–20 rad/s | How fast steering reaches its target. Lower feels heavier. |
SteeringSpeedSensitivity |
0–1 s/m | Reduces available angle as speed rises. Zero disables. |
SteeringRateSpeedSensitivity |
0–1 s/m | Reduces response rate as speed rises. |
DragCoefficientArea |
0–30 m² | Drag coefficient times frontal area, not the coefficient alone. |
AirDensity |
0–5 kg/m³ | Keep a sensible atmosphere rather than using it as an upgrade. |
angle_limit = SteeringAngleLimit / (1 + abs(forward_speed) × SteeringSpeedSensitivity)
steering_rate = SteeringRate / (1 + abs(forward_speed) × SteeringRateSpeedSensitivity)
Drag opposes velocity and grows with its square. Zeroing both drag and rolling loss to hit a number also ruins coasting and downhill behaviour.
Upgrade presets
Presets are always recomputed from the current model baseline, never multiplied onto the previous upgrade, so repeating one never compounds.
| Preset | Input | What it does |
|---|---|---|
| Engine level | 0–4 | Baseline torque and target ×1.00 / 1.10 / 1.20 / 1.30 / 1.40, with taller final drive and redline headroom. |
| Top speed | 20–200 mph | A full performance preset: torque from the squared speed ratio, taller gearing, new target. |
| Suspension firmness | 0.5–2 | Springs and both anti-roll rates ×factor, base damping ×√factor. Keeps the chosen height. |
| Suspension height | −0.2 to 0.3 m | Baseline rest length plus offset. Keeps the chosen firmness. |
On an 80 mph car, engine levels request 80, 88, 96, 104 and 112 mph. Level 4 is plus forty percent, not double.
The top-speed preset and engine levels work differently, so do not reach for setTopSpeedMph when you only want to lower the governor: edit MaxSpeedMps directly for that.
When the model baseline changes, valid presets are rebased onto it, custom top-speed presets keep their mph, and raw overrides on the fields you just edited give way. Re-read effective handling afterwards. The exact calls are in the API reference.
A tuning order that works
- Baseline. Record versions, profile, effective handling, transmission mode, damage and upgrade state. Repair or respawn the car, close the menu, engine running.
- Geometry before power. Tyre radius, mounts, body bounds, clearance, four accepted contacts on level road. A chassis dragging on the road cannot be fixed with torque.
- Ride height and travel. Loaded length against minimum and rest. Leave compression travel; the underside must clear without the wheels floating.
- Settle the suspension. One repeatable bump slowly. Springs and base damping in modest steps, then compression and rebound separately. A row of bumps exposes rebound problems.
- Drivetrain. Driven wheels, gear changes, top-gear redline speed above your target. Then torque, judged by actual acceleration rather than engine pitch.
- Grip and brakes. Straight braking and acceleration on one surface. Balance longitudinal against lateral without killing all slip. Test handbrake release on a slope.
- Cornering. Steady radius at low then moderate speed, then a lane change. Change response and anti-roll separately. Check the second client before calling drift a grip problem.
- Extremes. Long straight, hill, bumps, a jump, rollover, collision, water, ownership transfer. Record failures instead of compensating elsewhere.
- Save what you accepted. Persist the whole intended patch, restart the core, spawn fresh and retest briefly.
Five to ten percent is a sensible experimental step. Keep the previous exact values so you can go back.
Under-terrain recovery
A car that ends up under the map is put back without a respawn. The controller keeps a recent safe pose, recorded while all four wheels had fresh static contact under an upright dry body, and only accepts one from the last four seconds and within forty metres. To act on it, it has to witness the body crossing down through an upward-facing static surface along real recent movement, confirm more than a metre of penetration with a second ray, and see no wheel support. Being flipped, airborne or simply low in the world never triggers it, and no highest-ground query is used, so the road above a cave is not a destination.
The saved point is checked again at all four contacts, a coarse cabin test rejects it if something is standing there, and the car is then restored with fifteen centimetres of clearance, velocity and solver history cleared, a 150 ms freeze and a five second cooldown. It is the same chassis: occupants and assembled parts come with it, nothing is repaired, no plate is rerolled and no handling value changes.
It is a safety net, not a guarantee. No recent safe pose, missing terrain, an obstructed return point or an ownership change makes it skip. A successful return prints one line to the console and nothing to chat.
When something is wrong
| Symptom | Check first |
|---|---|
| Wheels spin, car barely moves | Driven-wheel contacts, normal loads, slip, chassis collision, brakes, flooding, ownership |
| Feels stuck in first gear | Real gear and RPM, transmission mode, bindings, driven-wheel support, ratios. Audio is not telemetry |
| More torque, same top speed | Gearing, redline, governor target, drag equilibrium, slope, host ceiling |
| Bounces standing still | Mounts, radius, self-collision, static clearance, contact freshness, then damper balance |
| Glued to the ground | Rebound damping, stale contact diagnostics, rest logic. Compare supported and airborne frames |
| Falls through the road | Streaming and native body collision, probe acceptance, sample age. Grip cannot load missing collision |
| Others see it drifting sideways | Ownership, replicated heading, snapshot age, contact projection. Compare owner and remote views |
| Cannot climb a hill | Drive axle support, wheel load and slip, torque and gearing, body scraping |
| Editor rejects a sane value | Cross-field constraints, every affected car stopped, read-only fields, the installed schema |
| A saved value reverted | Whether the field was actually in the saved patch, correct profile, both journal files |
| JSON edit did nothing | Restart the core, then check saved overrides and instance upgrades against effective handling |
For speed, keep your measurements straight: telemetry.speed is signed forward m/s, while getSpeed is absolute 3D speed including vertical movement. A jump adds vertical speed and wheel RPM can rise with no forward travel. At a steady top speed, near-zero acceleration is normal because forces balance.
To record a run, enable developer debug for the test and turn it off afterwards. A useful pattern is: fresh car, wait 3 s, engine on, accelerate on a safe level straight for 30 s, brake fully, wait 10 s, exit. Do hills, bumps and ownership migration as separate runs rather than one unexplained number. Diagnostics land in the core resource under exports/diagnostics/.