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.
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 modelscamerasInternal section for the camera, set up to be unavailable when unseatedcargoStorage section for dynamic weight and stiffness changeoccupantSlots section with its settings linked to slot variablestriggers2 and triggerEventLinks2 sections set up to highlight the seat when hovered over and seat/unseat when clickednodes, beams and triangles: physical structure of the occupant, including attachment to the seatThe 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.
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.
Once the occupant is added, the slot variables have to be set up.
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.
These are only used in special cases.
Valid values are “left”, “right” and “center”.
Only use if the default behavior is incorrect after setting up everything else.
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.
ref: camera nodeleft: camera nodeback: camera nodeunrestricted permissionsThere 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.
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.
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},
],
},
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:
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.
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”.
Valid arguments:
Driver Seat with driver permission, Passenger Seat otherwiseexitSide if exists, otherwise driverSide if exists, otherwise left when id ends with L, right when ends with R, center otherwiseright when id ends with R and left otherwiseunrestricted permissions_action.json files in lua/ge/extensions/core/input/actions folder.camerasInternal section which has the occupantSlotId matching the id of this slotCustom 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}
}],
],
Was this article helpful?