Occupant Slots

This feature is supported as of BeamNG.tech and .drive version 0.40 to latest.

Occupant Slots section adds occupants (driver and passengers) to a vehicle. It manages their permissions, cameras, visibility, color, and dynamic weight change.

In BeamNG, every vehicle has at most 6 seats with occupant slots. Every occupant slot houses an occupant at all times. One of them is the driver seat, which houses an occupant with permissions to control the vehicle. Every occupant slot has some amount of weight even when not used - that is done for stability reasons.

When an occupant slot is “seated”, it simulates an occupant on the seat. Its nodes have increased weight which adds up to approximately 89kg. Its beams get stiffer in order to hold the added weight and reduce the ‘squishiness’ of the collision structure. A 3D model of a seat occupant also becomes visible - it consists of 2 parts, character_torso and character_head, which cannot be changed. When a player switches to the occupant’s camera, the occupant’s character_head becomes invisible, except for mirrors and other reflections (in case of split screen view, that only happens on that player’s view).

“Unseating” the seat makes the 3D model invisible, changes the weight back to default, and softens the beams again. The collision structure of a character exists on the seat at all times, however it is soft enough when not seated that it does not meaningfully influence the vehicle deformation.

Many occupant slots can be “seated” at the same time, whether by multiple players in split-screen mode or by “dummies” used for testing purposes. “Dummies” will have random colors, split screen players will have colors matching their controllers, single player character is gray. This behavior cannot be changed.

Default occupant

All vehicles in the base game use a single dynamic Jbeam file for the occupant for easier maintenance. It is located in the vehicles/common/passengers folder. It contains the following:

  • flexbodies and props sections for the occupant, using the supported 3D models
  • camerasInternal section for the camera, set up to be unavailable when unseated
  • cargoStorage section for dynamic weight and stiffness change
  • occupantSlots section with its settings linked to slot variables
  • triggers2 and triggerEventLinks2 sections set up to highlight the seat when hovered over and seat/unseat when clicked
  • nodes, beams and triangles: physical structure of the occupant, including attachment to the seat

The default occupant weighs roughly 6kg when unseated (can be reduced by roughly 1kg if using dedicated existing camera nodes instead of auto generated ones) and 89kg when seated.

Do not edit the default occupant Jbeam file! It is very risky and not intended, it can break in a lot of edge cases if not done properly.

In order to use the occupant on a mod vehicle, you need to add a slot for this part on the seat you want the character on, for example:

"slots2": [
    ["name", "allowTypes", "denyTypes", "default", "description"],
    ["seat_occupant_FL", ["seat_occupant"], [], "occupant_generic", "Front Left Seat Occupant", {
        "coreSlot":true,
        "nodeMove":{"x":0.305,"y":-0.055,"z":0.6},
        "nodeRotate1":{"x":-21, "y":0, "z":0},
        "variables": {
            "$seatID": "FL",
            "$TriggerHighlightMesh": "autobello_seat_FL",
            "$occupant_camPitch": 21,
            "$occupantDragCoef": 1,
            "$seatAttachmentStrength": "FLT_MAX",
            "$occupant_attachnodeFL": "sf1ll",
            "$occupant_attachnodeFR": "sf1l",
            "$occupant_attachnodeRL": "sf2ll",
            "$occupant_attachnodeRR": "sf2l",
            "$occupant_attachnodeTL": "sf3ll",
            "$occupant_attachnodeTR": "sf3l",
            "$occupant_attachnodeRigifier": "sf4l"
        }
    }],
],

In this setup, nodeMove is the position of the occupant, and nodeRotate1 is the rotation. Alternative properties such as nodeMove2 or nodeRotate3 can be used instead or additionally if required. Make sure to set up the position and rotation in a way that there is no collision fighting between the nodes of the occupant and the triangles of the seat.

Required slot variables

Once the occupant is added, the slot variables have to be set up.

string
type
Unique identifier
Must be different for each passenger.
string
type
Mesh to highlight when hovering over the trigger
When none provided, the trigger will be a box.
number
type
0
default
Camera pitch to offset nodeRotate rotation
Should be negative of nodeRotate1 on X axis.
number
type
50
default
Drag coefficient of the occupant
Should be 1 on fully enclosed vehicles, can be higher on open-top ones depending how open it is.
number or string
type
150000
default
Strength of the beams attaching the occupant to the seat
Should be “FLT_MAX” on fully enclosed vehicles, can be lower on open-top ones.

string
type
Front left seat node name
string
type
Front right seat node name
string
type
Rear left seat node name
string
type
Rear right seat node name
string
type
Top left seat node name
string
type
Top right seat node name
string
type
Seat back rigidifier node name

Vehicles prior to the 0.40 update had no rigidifier nodes for the seat back. You may want to add such node to the seat structure if your seat doesn’t have it. Reference official vehicles on how it should be positioned relative to the other nodes.

Optional slot variables

These are only used in special cases.

string
type
Seat name displayed on the UI
Only to be used when the default is misleading, because this doesn’t support translation to different languages.
string
type
Overwrites which side (if any) the camera will lean to when looking back ’through the window'

Valid values are “left”, “right” and “center”.

Only use if the default behavior is incorrect after setting up everything else.

string
type
Overwrites which side of the car the walking mode character spawns on when entering walking mode from this seat

Valid values are “left” and “right”, and also short variants “l” and “r”.

Only use if the default behavior is incorrect after setting up everything else.

boolean
type
Further override for the previous option
Only use if the default behavior is incorrect after setting up everything else.
string
type
occupant head node
default
If provided, when exiting the car from this seat, the walking mode character will spawn next to that node
Only use if the default behavior is incorrect after setting up everything else.
dictionary
type
{}
default
Overwrite camera settings
Use the same parameters as with camerasInternal.

string
type
auto generated node
default
Overwrite which node serves as the ref: camera node
All 3 of these should be used together. These nodes should be set perfectly aligned with each other like the vehicle’s main refNodes, and should be close to the occupant’s camera node.
string
type
auto generated node
default
Overwrite which node serves as the left: camera node
All 3 of these should be used together. These nodes should be set perfectly aligned with each other like the vehicle’s main refNodes, and should be close to the occupant’s camera node.
string
type
auto generated node
default
Overwrite which node serves as the back: camera node
All 3 of these should be used together. These nodes should be set perfectly aligned with each other like the vehicle’s main refNodes, and should be close to the occupant’s camera node.

boolean
type
true
default
Allows disabling selfCollision on the occupant nodes closest to the seat
Use if self-collision issues are not fixable otherwise.
string
type
Optional secondary mesh to highlight when hovering over the trigger
When none provided, only the primary mesh is used.
string or array
type
[]
default
Additional action(s) allowed for an occupant with unrestricted permissions
This doesn’t do anything by default, it is only provided as a template for custom occupants. Do not use this.

Additional variable for driver seat

There is an additional variable required, passed from the higher level of the slots system. Where the slot for the driver seat is:

["autobello_seat_FL", ["autobello_seat_FL"], [], "autobello_seat_FL", "Driver Seat", {"variables":{"$isDriver":"LHD"}}],

It is only set for the driver seat. The allowed values are ‘LHD’ and ‘RHD’, depending which side the driver seat is on. The reason this one is separate, is because there are vehicles with both LHD and RHD interior options, which use the same Jbeam files for both front seats. This is very important to add, because it marks the occupant as the driver, giving it permission to control the vehicle - without that, the vehicle cannot be driven while in its camera.

Cargo load box slots

If the seat already has a slot for something other than the passengers - such as cargo load boxes - it will need an additional middle slot to choose whether the space on the seat is reserved for the occupants or the cargo:

"autobello_seats_R": {
    "information":{
        "authors":"BeamNG",
        "name":"Rear Bench Seat",
        "value":450,
    },
    "slotType" : "autobello_seats_R",
    "slots2": [
        ["name", "allowTypes", "denyTypes", "default", "description"],
        ["autobello_seats_R_space", ["autobello_seats_R_space"], [], "autobello_seats_R_occupants", "Rear Seat Space", {"coreSlot":true}],
    ],

(...)
},

"autobello_seats_R_occupants": {
    "information":{
        "authors":"BeamNG",
        "name":"Rear Seat Occupants Space",
        "value":0,
    },
    "slotType" : "autobello_seats_R_space",
    "slots2": [
        ["name", "allowTypes", "denyTypes", "default", "description"],
        ["seat_occupant_RL", ["seat_occupant"], [], "occupant_generic", "Rear Left Seat Occupant", {
            "coreSlot":true,
            "nodeMove":{"x":0.24,"y":0.60,"z":0.60},
            "nodeRotate1":{"x":-23, "y":0, "z":0},
            "variables": {
                "$seatID": "RL",
                "$TriggerHighlightMesh": "autobello_seats_R",
                "$occupant_camPitch": 23,
                "$occupantDragCoef": 1,
                "$seatAttachmentStrength": "FLT_MAX",
                "$occupant_attachnodeFL": "srr1ll",
                "$occupant_attachnodeFR": "srr1rr",
                "$occupant_attachnodeRL": "srr2ll",
                "$occupant_attachnodeRR": "srr2rr",
                "$occupant_attachnodeTL": "srr3ll",
                "$occupant_attachnodeTR": "srr3rr",
                "$occupant_attachnodeRigifier": "srr4l"
            }
        }],
        ["seat_occupant_RR", ["seat_occupant"], [], "occupant_generic", "Rear Right Seat Occupant", {
            "coreSlot":true,
            "nodeMove":{"x":-0.24,"y":0.60,"z":0.60},
            "nodeRotate1":{"x":-23, "y":0, "z":0},
            "variables": {
                "$seatID": "RR",
                "$TriggerHighlightMesh": "autobello_seats_R",
                "$occupant_camPitch": 23,
                "$occupantDragCoef": 1,
                "$seatAttachmentStrength": "FLT_MAX",
                "$occupant_attachnodeFL": "srr1ll",
                "$occupant_attachnodeFR": "srr1rr",
                "$occupant_attachnodeRL": "srr2ll",
                "$occupant_attachnodeRR": "srr2rr",
                "$occupant_attachnodeTL": "srr3ll",
                "$occupant_attachnodeTR": "srr3rr",
                "$occupant_attachnodeRigifier": "srr4r"
            }
        }],
    ],
},

"autobello_seats_R_cargo": {
    "information":{
        "authors":"BeamNG",
        "name":"Rear Seat Cargo Load",
        "value":0,
    },
    "slotType" : "autobello_seats_R_space",
    "slots2": [
        ["name", "allowTypes", "denyTypes", "default", "description"],
        ["load_seat_R", ["load_seat_R"], [], "", "Rear Seat Load", {
            "coreSlot":true,
            "nodeMove":{"x": 0.00, "y":0.52, "z":0.69},
            "variables":{
                "$rotx":-15, "$roty":0, "$rotz":0,
                "$group":"seat_box_R",
            },
        }],
    ],
    "beams":[
       ["id1:",       "id2:"],
       {"beamPrecompression":1, "beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},

       //cargo load box
       {"beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},
       {"beamSpring":500001,"beamDamp":250},
       {"beamDeform":510000,"beamStrength":"FLT_MAX"},
       {"optional":true},
       ["seat_box_R", "srr1rr"],
       ["seat_box_R", "srr1ll"],
       ["seat_box_R", "srr2rr"],
       ["seat_box_R", "srr2ll"],
       ["seat_box_R", "srr3rr"],
       ["seat_box_R", "srr3ll"],
       {"optional":false},
   ],
},

Cargo load boxes on front seats are no longer equippable on official vehicles.

Common racing seats

New common racing seats added in version 0.40 (different from the legacy racing seats) have occupants by default. All you need is adding a slot and attach beams for those seats. You should use the same attach beams as the stock seats, but with increased beamSpring and beamDamp properties to make them sit stiffer - the added weight of the race seats allows for stiffer attachment. The same applies to common vintage and off-road seats.

"autobello_race_seat_FL": {
    "information":{
        "authors":"BeamNG",
        "name":"Front Left Race Seat Base",
        "value":10,
    },
    "slotType" : "autobello_seat_FL",
    "slots2": [
        ["name",         "allowTypes",     "denyTypes", "default",      "description"],
        ["race_seat_FL", ["racing_seat"],  [],          "seat_race_gray", "Front Left Race Seat", {"nodeMove":{"x":0.3, "y":-0.04, "z":0.3}, "variables":{"$seatID":"FL"}}],
    ],
    "flexbodies": [
        ["mesh", "[group]:", "nonFlexMaterials"],
        ["racingseat_base", ["seat_race_FL","floor"],[],{"pos":{"x":0.3,"y":-0.04,"z":0.28}, "scale":{"x":0.95, "y":0.95, "z":1.33}}],
    ],
    "beams": [
        ["id1:",  "id2:"],
        {"deformLimitExpansion":1.2},
        {"beamPrecompression":1, "beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},
        //attach
        {"beamSpring":1501000,"beamDamp":150},
        {"beamDeform":5000,"beamStrength":"FLT_MAX"},
        {"deformLimitExpansion":""},

        //strong
        ["seatGeneric2l_FL", "b4l"],
        ["seatGeneric2l_FL", "b3l"],
        ["seatGeneric1l_FL", "b3l"],
        ["seatGeneric1l_FL", "b2l"],
        ["seatGeneric1r_FL", "b2ll"],
        ["seatGeneric1r_FL", "b3ll"],
        ["seatGeneric2r_FL", "b3ll"],
        ["seatGeneric2r_FL", "b4ll"],
        ["seatGeneric2l_FL", "b4r"],
        ["seatGeneric2l_FL", "b3r"],
        ["seatGeneric1l_FL", "b3r"],
        ["seatGeneric2r_FL", "b4l"],
        ["seatGeneric1r_FL", "b3l"],

        //weaker
        {"beamSpring":401000,"beamDamp":150},
        ["seatGeneric2l_FL", "b4ll"],
        ["seatGeneric1l_FL", "b3ll"],

        {"breakGroup":""},
        {"deformLimitExpansion":1.2},
        {"beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},
    ],
},
"autobello_race_seat_FR": {
    "information":{
        "authors":"BeamNG",
        "name":"Front Right Race Seat Base",
        "value":10,
    },
    "slotType" : "autobello_seat_FR",
    "slots2": [
        ["name",         "allowTypes",     "denyTypes", "default",      "description"],
        ["race_seat_FR", ["racing_seat"],  [],          "seat_race_gray", "Front Right Race Seat", {"nodeMove":{"x":-0.30, "y":-0.04, "z":0.3}, "variables":{"$seatID":"FR"}}],
    ],
    "flexbodies": [
        ["mesh", "[group]:", "nonFlexMaterials"],
        ["racingseat_base", ["seat_race_FR","floor"],[],{"pos":{"x":-0.3,"y":-0.04,"z":0.28}, "scale":{"x":0.95, "y":0.95, "z":1.33}}],
    ],
    "beams": [
        ["id1:",  "id2:"],
        {"deformLimitExpansion":1.2},
        {"beamPrecompression":1, "beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},
        //attach
        {"beamSpring":1501000,"beamDamp":250},
        {"beamDeform":5000,"beamStrength":"FLT_MAX"},
        {"deformLimitExpansion":""},

        //strong
        ["seatGeneric2r_FR", "b4r"],
        ["seatGeneric2r_FR", "b3r"],
        ["seatGeneric1r_FR", "b3r"],
        ["seatGeneric1r_FR", "b2r"],
        ["seatGeneric1l_FR", "b2rr"],
        ["seatGeneric1l_FR", "b3rr"],
        ["seatGeneric2l_FR", "b3rr"],
        ["seatGeneric2l_FR", "b4rr"],
        ["seatGeneric2r_FR", "b4l"],
        ["seatGeneric2r_FR", "b3l"],
        ["seatGeneric1r_FR", "b3l"],
        ["seatGeneric2l_FR", "b4r"],
        ["seatGeneric1l_FR", "b3r"],

        //weaker
        {"beamSpring":401000,"beamDamp":150},
        ["seatGeneric2r_FR", "b4rr"],
        ["seatGeneric1r_FR", "b3rr"],

        {"breakGroup":""},
        {"deformLimitExpansion":1.2},
        {"beamType":"|NORMAL", "beamLongBound":1.0, "beamShortBound":1.0},
    ],
},

Activating the system

The occupant slots system is not active by default, it has to be explicitly activated per vehicle for backwards compatibility reasons. After setting it up, you have to add a new section to the vehicle’s main Jbeam file:

"occupantSystem": {
    "enabled": true,
    "version": 1
},

The version may change in the future and will have to be manually updated by the mod’s author to support newer features.

After the system is activated, you might enconter some common issues:

  • The attachment of the seat to the floor of the vehicle might not be stiff enough to hold the weight of the occupant. Make it as stiff as you can without sacrifising the deformation behavior - this is important to prevent excessive shake when in occupant camera.
  • The added weight of the occupants will increase the overall weight of the vehicle - roughly 6kg for each unseated occupant, and some extra weight for the seat rigidifier nodes. You may want to remove this weight from unimportant parts of the vehicle instead if you want to return it to the previous weight. Also remember about the extra 89kg for the driver - if your vehicle already simulated the driver’s weight in some other way, you should remove that.
  • The vehicle might veer to one side as a result of the added driver weight - this is common on real life vehicles as well, although in some cases it is compensated by tweaking the steering center or making the springs stiffer on one side.

ADVANCED: Custom occupant slots

This advanced section is NOT for BeamNG.drive modders!

Do not make custom occupants, use the default one instead, otherwise your mod can break in following updates! No backwards compatibility or support is provided!

Some features, such as using a custom 3D model for an occupant, are not supported yet at this time. If you wish to add custom driver/passenger characters to cars, do that with the standard part and slot system, not the occupant system.

It is possible to add an occupantSlots section manually like any other Jbeam section. That only works when the file path contains occupant_generic, either in the file name or a sub-folder name.

Required arguments

string
type
Unique identifier

Named after a seat in the vehicle for convenience, for example an occupant of “Front Left Seat” would have the id value “FL”.

This has to match a cargo group . In order to support occupants, the groupId must follow the naming convention [seat Id]Occupant, for example FLOccupant for seat Id “FL”.

string
type
passenger
default
Determines the permissions granted to the player seated on this slot

Valid arguments:

  • “driver”: Grants permission to control the vehicle and use vehicle triggers.
  • “passenger”: Grants only permission to use vehicle triggers.
  • “unrestricted”: Grants permission to control the vehicle, use vehicle triggers, and use any additional actions provided in the “actionMaps” table.
string
type
enterSeat_[id]
default
Id or name of the trigger linked to the slot
The trigger (using triggers2 system) must have the inputAction “common:enterSeat” linked in triggerEventLinks2. When clicked, the player will be seated in the occupant slot linked to this trigger. This works both for entering the car from walking mode and for changing seats within the car.
string
type
[id]_Occupant
default
Cargo Storage group linked to the occupant slot
Nodes with this cargo group will gain weight when the slot is seated, and beams with this group will gain stiffness.

Optional arguments

string
type
Driver Seat with driver permission, Passenger Seat otherwise
default
Displayed name of the seat
string
type
exitSide if exists, otherwise driverSide if exists, otherwise left when id ends with L, right when ends with R, center otherwise
default
Determines which side (if any) the camera will lean to when looking back ’through the window'
Valid values are “left”, “right” and “center”.
string
type
The side on which the linked trigger is on if exists, otherwise right when id ends with R and left otherwise
default
Which side of the car the walking mode character spawns on when entering walking mode from this seat
Valid values are “left” and “right”, and also short variants “l” and “r”.
string
type
If provided, when exiting the car from this seat, the walking mode character will spawn next to that node
Overwrites exitSide.
string
type
Fallback for seatSide and exitSide
Valid values are “left” and “right”. Used just in case a mod vehicle does something weird with the occupant from common folder.
string or array
type
[]
default
Additional action(s) allowed for an occupant with unrestricted permissions
These specific action maps for the occupant permission system have to be _action.json files in lua/ge/extensions/core/input/actions folder.
dictionary
type
Settings of an existing camera from camerasInternal section which has the occupantSlotId matching the id of this slot
default
Camera settings
If needed, they can be overwriten with a custom dictionary.

Advanced example

Custom occupant with custom permissions and camera properties override

"occupantSlots":[
    ["id", "defaultPermissionMode", "entryTrigger", "cargoGroup"],
    ["FL", "unrestricted", "enterSeat_FL", "FLOccupant", {
        "displayName":"FL",
        "exitNode":"head",
        "exitSide":"left",
        "seatSide":"left",
        "driverSide":"left",
        "actionMaps":["customAction1","customAction2"],
        "camera":{"fov":60,"canRotate":false}
    }],
],
Last modified: October 19, 2026

Any further questions?

Join our discord
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.