Hungrit Docs

Vehicles#

A vehicle is an object somebody can get into and drive: a car, a bike, a truck, a boat, a plane.

Use it to

  • turn an object into something people can get into and drive
  • start from a preset like a car, a truck or a bike
  • tune the engine, wheels, brakes and steering
  • make boats float and planes lift
  • drive one from a script, with nobody inside
A car
local self = require("self") self:vehicle({ preset = "car" })

That is a whole car. Click it to get in: W / S drive and brake, A / D steer, Space is the handbrake, Shift is the boost, F gets out.

The object can be one box or a model made of parts. Either way it becomes one body that the physics moves, and it is driven without delay: the driver's own game simulates the car while the region checks it.


The presets#

presetWhat you get
"car"A road car. Front-wheel drive, grips, runs wide rather than spinning.
"drift"Rear-wheel drive, a lot of power and steering lock. The handbrake throws the tail out and the throttle holds it there.
"offroad"Four-wheel drive, long soft suspension, climbs.
"truck"Heavy, slow to turn, strong engine brake.
"bike"Two wheels. Leans into the turn by itself and stands back up.
"boat"A propeller and a keel. Floats on any water, rides up as it speeds up.
"plane"Wings, a tail, an engine and landing gear. Takes off, climbs, banks.

A preset is a starting point. Every number in it can be replaced, and only the ones you name change:

A faster drift car that lets go sooner
self:vehicle({    preset = "drift",    mass = 1100,    engine = { power = 400, top_speed = 240 },    wheels = { rear = { grip = 0.85 } },})

self:vehicle(options) → true, or nil, reason

A misspelt option is refused on the line that wrote it, with the names it could have been:

Luau
local ok, why = self:vehicle({ engine = { powr = 400 } })-- nil, "unknown option 'engine.powr' (it has: power, top_speed, gears, ...)"

self:vehicle(false) stops the object being a vehicle.

Wheels and seats, by name#

When the object is a model made of parts, the vehicle reads the parts' names:

A part whose name containsBecomes
wheel, tire, tyre, roda, pneua wheel, where the part is and as big as the part
front or back / rear in a wheel's namewhich end of the vehicle is the front
seat, banco, assentoa seat
driver, pilot, motorista, pilotothe driver's seat

So a downloaded car whose wheels are called wheel-front-left, wheel-back-right and so on needs nothing more than the one line. The wheel parts turn, steer and ride on their suspension by themselves.

With no wheel parts, a car or a bike gets wheels at the corners of its body, which work the same and are simply not drawn. With no seat part, the vehicle itself is the driver's seat.

A seat is an ordinary seat: its place and direction are set in the editor's Physics page, live, while you sit in it. The Driver's seat switch there says which one drives.

Which way is the front#

The front is read from the wheels' names when they say. Otherwise it is the object's forward (-z), or +x when the object is longer along x. Say it when the model points another way:

Luau
self:vehicle({ preset = "car", front = "+z" })   -- "-z", "+z", "+x" or "-x"

The options#

Positions are in the object's own frame, in metres.

engine#

OptionMeaningcar
powerpeak power, horsepower. 0 = no engine150
top_speedkm/h it tops out at180
gearsforward gears; it shifts by itself5
redline, idlerev range, for a rev counter or a sound6500, 900
reverse_speedkm/h in reverse35
engine_brakehow hard it slows with the throttle closed, m/s²1.2
boostpower multiplier while Shift is held. 1 = none1

wheels#

Fields given directly apply to every wheel. front = { … } and rear = { … } apply to one end. A list replaces the wheels altogether.

OptionMeaningcar
griptyre grip. 1.0 is a road tyre on dry road1.05 front, 1.25 rear
slideshare of the grip left once the tyre slides. Lower holds a drift longer0.8
slip_peakdegrees of slip at peak grip. Higher forgives more9 front, 7.5 rear
travelsuspension travel, metres0.2
stiffnessride frequency, Hz. 1.2 is soft, 2.5 is a race car1.8
damping0.3 bounces, 1.0 never overshoots0.55
steershare of the steering this wheel takes1 front, 0 rear
driveshare of the engine it receives1 front, 0 rear
brake, handbrakeshare of each brake1, rear only
radiusmetres. 0 = the part's own size0

stiffness and damping do not depend on the vehicle's weight: the same numbers ride the same on a kart and on a truck. And the vehicle always sits at the height it was modelled at, whatever it weighs.

Soft, tall suspension for every wheel; a looser rear
self:vehicle({    preset = "car",    wheels = { all = { travel = 0.35, stiffness = 1.3 }, rear = { grip = 1.0 } },})

More grip behind than in front makes a car that runs wide at the limit and does not spin. Less grip behind makes one that oversteers. That one balance is most of how a car feels.

steering#

OptionMeaningcar
anglefull lock, degrees34
speedhow fast the wheels follow the key, degrees per second140
high_speedshare of the lock left at top speed0.22
assist0..1: how much the lock is held to what the tyres can use1
driftdegrees of slide the assist holds with the key down10

drift is the dial between a car that never spins and a car that drifts. With the steering key held, the assist lets the tail hang out this far and then turns the wheels the other way by itself. 10 is a road car; 40 is a drift car. assist = 0 is a raw wheel with no help at all.

brakes#

OptionMeaningcar
forcefoot brake, in g1.1
handbrakehandbrake, in g, on the wheels that have handbrake2.0

aero#

OptionMeaningcar
downforceextra weight pressing it down at 100 km/h, as a share of its own0.15
dragair drag. 0 = worked out from top_speed0

assist#

OptionMeaningcar
anti_rollanti-roll bar. 0 leans like a boat0.35
low_centrehow far the weight is lowered. Higher is harder to roll over0.45
traction0..1: how much wheelspin is cut0
balance0..1: keeps it upright along its length. A bike needs 10
leandegrees a balanced vehicle leans into a turn0

thrusters#

A force at a point: a propeller, a jet, a rocket. A list.

OptionMeaning
poswhere it pushes from
dirwhich way it pushes the vehicle. Default is forward
accelacceleration it gives the vehicle at full power, m/s²
top_speedkm/h at which it has nothing left. 0 = no limit
reverseshare of accel available backwards
steerdegrees the push swings with the steering: an outboard motor
axis"throttle" (W / S), "lever" (a plane's throttle), "boost" (Shift)
watertrue = only pushes under water
A rocket on the back of a car
local vec = require("vec") self:vehicle({    preset = "car",    thrusters = { { pos = vec(0, 0.5, 2), accel = 14, axis = "boost" } },})

wings#

A surface that lifts: lift across the airflow, drag along it. A list.

OptionMeaning
poswhere the lift acts
normalthe side the lift points to: up for a wing, sideways for a fin
aream²
liftlift per radian of angle of attack
stalldegrees past which it stops lifting
incidencedegrees of built-in angle
control"pitch", "roll", "yaw" or "none": which control deflects it
gaindegrees it deflects at full input

hull#

How the body sits in water, on top of the floating every object already does.

OptionMeaningboat
keelsideways resistance in water. What makes a boat turn instead of skating3
stabilityhow hard the water rights it when it heels14
planinghow much it rides up with speed. A planing hull is what makes a boat fast0.45

controls#

controls = "car" (the default) or "plane".

Key"car""plane"
W / Sdrive forward / brake, then reversenose down / nose up
A / Dsteerroll, with the rudder following
Spacehandbrakewheel brakes
Shiftboostthrottle up
Ctrlthrottle down
Fget outget out

Reading it#

vehicle_state#

self:vehicle_state() → a table, or nil when the object is not a vehicle

FieldMeaning
speed, kmhalong its front, m/s and km/h. Negative in reverse
rpm, gearengine revs, and the gear: 1 up, -1 in reverse
throttle, steerwhat is being asked of it now
wheels, groundedhow many wheels it has, and how many are on the ground
slip0 gripping .. 1 sliding, the worst wheel
levera plane's throttle lever, 0..1
in_watertrue while it floats
driverthe id of whoever is in the driver's seat, or nil
A speedometer for the driver
local self = require("self")local players = require("players") self:vehicle({ preset = "car" }) local DASH = {    id = "dash", size = { 150, 60 }, vars = { kmh = 0, gear = 1 },    pages = { main = {        { "text", "{kmh} km/h", size = 22, align = "center" },        { "text", "gear {gear}", size = 12, align = "center" },    } },} self:on_sit(function(p)    p:show_hud(DASH)end) self:on_stand(function(p)    p:hide_hud("dash")end) self:on_timer(0.2, function()    local v = self:vehicle_state()    local p = v and v.driver and players:get(v.driver)    if p then        p:update_hud("dash", { kmh = math.floor(math.abs(v.kmh)), gear = v.gear })    endend)

vehicle_input#

self:vehicle_input(controls) → true, or nil, reason

The script drives. For a car with nobody in it: traffic, a taxi, a ghost.

FieldRange
throttle-1..1
steer-1..1, right is positive
brake, handbrake0..1
boosttrue / false
pitch, roll, yaw-1..1, for a plane
lever0..1, a plane's throttle

self:vehicle_input(nil) hands the vehicle back to whoever sits in the driver's seat.

A car that drives in a circle by itself
self:vehicle({ preset = "car" })self:vehicle_input({ throttle = 0.5, steer = 0.4 })

In multiplayer#

The driver's own machine runs the vehicle they drive. Steering, braking and the camera answer on the frame a key is pressed, at any ping. Everybody else sees the vehicle a moment behind, exactly in step with its driver's avatar.

The server checks every report it gets about a driven vehicle. It refuses a vehicle going faster than its own engine.top_speed (or its fastest thruster) allows, one that jumps from place to place, one that goes through a wall, and one under the ground. A refused vehicle goes back to the last place the server accepted.

  • A script that pushes a driven vehicle (self:push, self:set_velocity) takes it back from the driver for that moment. The push lands exactly as scripted.
  • A script driving with self:vehicle_input drives it on the server, and the driver's keys wait until self:vehicle_input(nil).
  • Getting out of a moving vehicle brakes it to a stop first. Holding the leave key gets out at once, whatever the vehicle is doing.

Loose physics objects work the same way while someone on foot pushes them. The pusher's machine moves the object, and the server keeps it within reach of that player. When a second player walks into the object, the server takes it back.


Common mistakes#

SymptomCause
it drives backwardsthe model faces the other way. Set front
the wheels do not turnthe wheel parts' names do not contain wheel. Rename them, or it uses unseen wheels at the corners
it spins every timeless grip behind than in front. Raise wheels.rear.grip, or lower steering.drift
it will not driftsteering.drift is small, or the rear grips too well. Start from preset = "drift"
it rolls over in cornersraise assist.low_centre and assist.anti_roll
the boat does not moveits thruster has water = true and is above the water. Lower its pos
the plane will not leave the groundit needs speed first: hold Shift down the runway, then S

See also#

Updated 17 October 2026