This document describes the items.level.json file format used by BeamNG levels to store scene objects.
items.level.json files are used inside level object folders such as:
levels/<levelName>/main/items.level.json
They store serialized scene objects as line-delimited JSON, meaning each line is one complete JSON object.
BeamNG levels store many scene objects as JSON objects. Instead of writing one large JSON array, the engine writes one object per line.
Example:
{"class":"SimGroup","name":"Environment"}
{"class":"TSStatic","name":"garage","shapeName":"/levels/example/art/shapes/garage.dae","position":[0,0,0],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1]}
{"class":"PointLight","name":"garage_light","position":[2,4,3],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1],"intensity":800}
This format is used because it is easy to stream, edit, diff, merge, and serialize incrementally.
The main level object file is usually:
levels/<levelName>/main/items.level.json
Additional object groups may be stored in subfolders:
levels/<levelName>/main/
├── items.level.json
├── Environment/
│ └── items.level.json
├── Buildings/
│ └── items.level.json
└── Gameplay/
└── items.level.json
Each folder can contain its own items.level.json.
items.level.json is not a normal JSON array.
Correct:
{"class":"SimGroup","name":"Buildings"}
{"class":"TSStatic","name":"building_01","shapeName":"/levels/example/art/shapes/building_01.dae"}
{"class":"TSStatic","name":"building_02","shapeName":"/levels/example/art/shapes/building_02.dae"}
Incorrect:
[
{"class":"SimGroup","name":"Buildings"},
{"class":"TSStatic","name":"building_01"},
{"class":"TSStatic","name":"building_02"}
]
items.level.json contents in [ ]. Each line must be a standalone JSON object.The engine loads items.level.json recursively.
When it finds a SimGroup object, it checks whether a folder with the same name exists. If it does, the engine loads that folder’s items.level.json as well.
Example root file:
{"class":"SimGroup","name":"Buildings"}
{"class":"SimGroup","name":"Gameplay"}
This causes the loader to look for:
main/Buildings/items.level.json
main/Gameplay/items.level.json
This allows large levels to organize objects into folders and groups.
Each line is a JSON object representing one serialized scene object.
Most objects contain at least:
| Field | Type | Description |
|---|---|---|
class |
string | Object class name, such as TSStatic, SimGroup, PointLight, TerrainBlock, etc. |
name |
string | Object name in the Scene Tree. |
position |
array[3] | Object position [x, y, z], when applicable. |
rotationMatrix |
array[9] | Object rotation as a 3×3 matrix, when applicable. |
scale |
array[3] | Object scale [x, y, z], when applicable. |
Different object classes can include many additional fields.
A group object used for organization.
{"class":"SimGroup","name":"Buildings"}
If a folder named Buildings exists next to the current items.level.json, it can contain its own nested object file:
Buildings/items.level.json
A static mesh object.
{
"class": "TSStatic",
"name": "garage",
"shapeName": "/levels/example/art/shapes/garage.dae",
"position": [0, 0, 0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1,1,1]
}
Important fields:
| Field | Description |
|---|---|
shapeName |
Path to the shape file. |
position |
Object position. |
rotationMatrix |
Object rotation. |
scale |
Object scale. |
A terrain object.
{
"class": "TerrainBlock",
"name": "theTerrain",
"terrainFile": "/levels/example/terrain/main.ter",
"position": [0,0,0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1,1,1],
"maxHeight": 2048,
"squareSize": 1
}
Important fields:
| Field | Description |
|---|---|
terrainFile |
Path to the terrain data file. |
maxHeight |
Maximum terrain height. Defaults to 2048 if missing. |
squareSize |
Size of one terrain square. Defaults to 1 if missing. |
A spawn point.
{
"class": "SpawnSphere",
"name": "default_spawn",
"position": [10, 20, 1],
"rotationMatrix": [1,0,0,0,1,0,0,0,1]
}
Spawn points are collected by name and position. The engine also adds a fallback spawn point named Zero at the origin.
A water plane object.
{
"class": "WaterPlane",
"name": "lake",
"position": [0,0,0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [100,100,1]
}
Many scene objects use these transform fields:
"position": [0, 0, 0]
A 3-value array:
[x, y, z]
"rotationMatrix": [
1,0,0,
0,1,0,
0,0,1
]
A 9-value 3×3 rotation matrix.
"scale": [1, 1, 1]
A 3-value scale vector:
[x, y, z]
If invalid transform values are found, the loader may default them to safe values such as:
position = [0, 0, 0]
rotation = identity matrix
scale = [1, 1, 1]
When writing line-object files, the engine can sort objects before saving.
There are two sorting modes:
If enabled, objects with a string serializeOrder field are sorted numerically.
{"class":"TSStatic","name":"a","serializeOrder":"10"}
{"class":"TSStatic","name":"b","serializeOrder":"20"}
The serializeOrder field is removed before writing the final object line.
If serializeOrder sorting is not used, objects are sorted by:
classnameThis gives stable output and makes files easier to diff.
The engine can save objects into namespace folders.
For example, an object namespace list may be saved as:
main/
├── Environment/
│ └── items.level.json
├── Gameplay/
│ └── items.level.json
└── Buildings/
└── items.level.json
Each namespace becomes a folder, and the entries inside it are written to that folder’s items.level.json.
During level loading, the engine starts from:
levels/<levelName>/main/
It then recursively loads:
items.level.json
from the main folder and any discovered SimGroup subfolders.
The resulting object list is then used to create scene objects.
Each line should:
class fieldInvalid lines are skipped and logged.
Manual editing is possible, but use care.
Recommended workflow:
Example levels/example/main/items.level.json:
{"class":"SimGroup","name":"Environment"}
{"class":"SpawnSphere","name":"default_spawn","position":[0,0,1],"rotationMatrix":[1,0,0,0,1,0,0,0,1]}
{"class":"TSStatic","name":"test_cube","shapeName":"/levels/example/art/shapes/test_cube.dae","position":[5,0,0],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1]}
Optional nested file:
levels/example/main/Environment/items.level.json
{"class":"PointLight","name":"env_light","position":[0,0,5],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1],"intensity":1000}
Possible causes:
classSimGroup nameCheck that the parent items.level.json contains:
{"class":"SimGroup","name":"GroupName"}
and that the folder exists:
GroupName/items.level.json
Possible causes:
position arrayCheck that rotationMatrix has exactly 9 numeric values.
Check that scale has exactly 3 numeric values.
items.level.json files store level objects as line-delimited JSON.
Key points:
SimGroup folders.position, rotationMatrix, and scale.serializeOrder, or by class and name.This format is compact, tool-friendly, and suitable for large levels with many scene objects.
Was this article helpful?