JBeam Basics
Introduction to the JBeam vehicle definition format — nodes, beams, triangles, slots, and variables.
JBeam is the JSON-based physics skeleton format that defines how vehicles (and other objects) behave in BeamNG's soft-body physics engine. Every vehicle is ultimately a collection of JBeam files describing its physical structure, visual meshes, and tunable parameters.
What JBeam Is
JBeam files define the physics mesh of a vehicle — mass points connected by springs. The game simulates each connection in real time, producing BeamNG's signature soft-body deformation. A typical vehicle workflow is:
- Model the visual mesh in Blender and export as DAE (Collada)
- Write JBeam files defining the physics structure and referencing the DAE
- Test in-game, iterate with Ctrl+L to live-reload
JBeam is case-sensitive and strict about syntax. Use a proper text editor (VSCode, Notepad++) and keep coordinates to 3 decimal places.
File Structure
JBeam files use a JSON-like format. Each file contains a top-level object where keys are part names:
{
"my_vehicle_body": {
"information": {
"name": "My Vehicle Body",
"authors": "YourName"
},
"slotType": "main",
"nodes": [
["id", "posX", "posY", "posZ"],
["n1", 0.0, 0.0, 0.5],
["n2", 0.5, 0.0, 0.5],
["n3", 0.0, 0.5, 0.5]
],
"beams": [
["id1:", "id2:"],
["n1", "n2"],
["n2", "n3"],
["n3", "n1"]
]
}
}JBeam uses a table format: the first row is a header defining column names, followed by data rows. The engine converts these arrays into keyed dictionaries at load time. Inline option dictionaries can be inserted between rows and accumulate to all following rows:
"beams": [
["id1:", "id2:"],
{"beamSpring": 5000, "beamDamp": 100},
["n1", "n2"],
["n2", "n3"],
{"beamSpring": 8000},
["n3", "n4"]
]Key Sections
Nodes
Nodes are individual mass points — the atoms of the physics mesh. Each node has an ID and a 3D position:
"nodes": [
["id", "posX", "posY", "posZ"],
["f1", 0.0, -2.0, 0.3],
["f2", 0.7, -2.0, 0.3],
["f3", -0.7, -2.0, 0.3]
]Positions are converted to vec3 values with optional transforms applied. Typical nodes weigh 2-3 kg each.
Beams
Beams are spring-damper connections between nodes — they form the structural skeleton:
"beams": [
["id1:", "id2:"],
{"beamSpring": 5000000, "beamDamp": 200},
["f1", "f2"],
["f2", "f3"]
]Beam types include: NORMAL (0), HYDRO (6), ANISOTROPIC (1), BOUNDED (2), PRESSURED (3), SUPPORT (7), LBEAM (4). The type determines how forces are calculated.
Triangles
Triangles define collision surfaces and pressure volumes. Three nodes form a face:
"triangles": [
["id1:", "id2:", "id3:"],
["f1", "f2", "f3"]
]Quads are also supported and are automatically converted to triangle pairs, with the diagonal chosen based on node distance for optimal mesh quality.
Flexbodies
Flexbodies reference the visual mesh (DAE model) and bind it to the physics nodes:
"flexbodies": [
["mesh", "[group]:", "nonFlexMaterials"],
["my_vehicle_body.dae", ["body_group"], []]
]Slots
Slots are attachment points enabling modular vehicle configurations. See the Slot System section below.
Variables
Variables are tunable parameters exposed in the parts configuration UI. See the Variables section below.
The Slot System
Slots make vehicles modular — a body can have slots for engine, transmission, wheels, bumpers, and more. Each slot defines a type, and parts declare which slot type they fit:
"slots": [
["type", "default", "description"],
["my_vehicle_engine", "my_vehicle_engine_v6", "Engine"]
]The engine resolves the full part tree from the vehicle config by recursively filling slots. Resolution priority:
- User-specified part (from vehicle config)
- Slot default part
- Empty (no part)
The slot system supports two versions:
- v1: Uses a
typefield for matching (legacy) - v2: Uses
allowTypes/denyTypesfor more flexible matching
Merge modifiers ($+, $*, $<, $>) control how child part data merges with parent data. The recursion limit is 50 levels deep.
Variables
Variables let modders expose tunable parameters to the in-game UI:
"variables": [
["name", "type", "unit", "category", "default", "min", "max", "title", "description"],
["$spring_rate", "range", "", "Suspension", 5000, 2000, 10000, "Spring Rate", "Front spring stiffness"]
]In any JBeam value, use $spring_rate for direct substitution. The variable system also supports:
$=expr— Expression evaluation (math with variables)$>>path— Component redirects$.name— Prefix/suffix expansion
Variables are scoped per slot — parent variables are available to child parts, and children can override parent values. Resolution is iterative (up to 400 iterations) with min/max/default constraints enforced.
How JBeam Files Are Loaded
The loading process handles parsing, validation, and optimization:
- I/O — Files are read and parsed from the vehicle directory
- Table schema processing — Array rows are converted to keyed dictionaries using header rows
- Slot resolution — The part tree is recursively resolved from the vehicle config
- Section merging — Parts are merged according to slot hierarchy and merge modifiers
- Variable substitution —
$variablesare resolved iteratively - Section processing — Individual sections (nodes, beams, etc.) are processed into runtime data
- Optimization — Final data is optimized for simulation performance
Rows with disable = true are skipped during processing. Special values like FLT_MAX and pipe-separated type flags (e.g., "|HYDRO|NM_steel") are handled during schema processing.
See Also
- JBeam Table Schema — How table format parsing works internally
- JBeam Slot System — Slot resolution, part matching, merge modifiers
- JBeam Variables — Variable scoping, expressions, and resolution
- JBeam Node & Beam Processing — How nodes, beams, hydros, and quads are processed
- Vehicle Modding Guide — Higher-level vehicle modding workflow
Understanding Vehicle Damage Systems
How BeamNG's three damage systems work together — beamstate for physics, damageTracker for gameplay, and partCondition for persistence.
Creating Vehicle Extensions
How to create Lua extensions that run in the Vehicle Engine (VE) context — structure, hooks, and differences from GE extensions.