This document describes BeamNG prefab files and how they are loaded by the engine.
Prefabs are reusable groups of scene objects. They allow several objects to be stored in a separate file and placed into a level as a single object.
BeamNG supports two prefab formats:
.prefab.prefab.json prefabsA prefab is represented in the level by a Prefab object. The Prefab object points to an external file using its filename field. When loaded, the prefab reads that file and creates a child SimGroup containing the objects stored inside.
Typical use cases:
Example level object:
{
"class": "Prefab",
"name": "gas_station_prefab",
"filename": "/levels/example/prefabs/gas_station.json",
"position": [100, 200, 0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1, 1, 1],
"loadMode": "Automatic"
}
| File | Purpose |
|---|---|
*.prefab.json |
Modern JSON prefab file. |
*.prefab |
Legacy TorqueScript prefab file. |
Prefab object |
Scene object that references and loads the prefab file. |
Root SimGroup |
Required group created by the prefab file. Contains all prefab children. |
| Field | Type | Description |
|---|---|---|
filename |
string | Path to the prefab file. Can point to .json or legacy .prefab. |
loadMode |
enum | Controls when the prefab is loaded. |
useGlobalTranslation |
bool | Changes how child transforms are applied. Mostly used for compatibility/special cases. |
Supported values:
| Value | Description |
|---|---|
Automatic |
Prefab loads automatically when the Prefab object is added. |
Manual |
Prefab does not load until explicitly loaded. |
Modern JSON prefabs are loaded when the filename contains .json.
A JSON prefab must create a root SimGroup. The engine expects one of the objects in the file to be a SimGroup, and that group becomes the prefab child group.
{"class":"SimGroup","name":"example_prefab_group"}
{"class":"TSStatic","name":"example_prop","shapeName":"/levels/example/art/shapes/prop.dae","position":[0,0,0],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1]}
SimGroup. If no SimGroup is created, the prefab will fail to load.JSON prefabs are commonly stored as line-based JSON object data, similar to level main object files. Each object is serialized as a JSON object.
A typical prefab contains:
SimGroupExample:
{"class":"SimGroup","name":"garage_prefab_group"}
{"class":"TSStatic","name":"garage_building","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":[0,2,3],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1],"intensity":800}
The root SimGroup acts as the container for all prefab objects.
When the prefab is loaded:
SimGroupSceneObjectsFor JSON prefabs, the root group may be renamed automatically to match the prefab name.
Example:
{"class":"SimGroup","name":"garage_group"}
A root SimGroup can contain noAutoReload.
{"class":"SimGroup","name":"garage_group","noAutoReload":true}
If noAutoReload is true, the prefab file is not tracked for automatic reload.
This can be useful when working with generated or special-purpose prefabs that should not reload automatically when the file changes.
Prefab children are stored with transforms relative to the prefab.
When the prefab is moved, rotated, or scaled, the child objects are updated.
The default behavior:
child final transform = prefab transform x stored child transform
child final scale = stored child scale x prefab scale
This allows the whole prefab to be moved as one object.
The useGlobalTranslation option changes how child transforms are applied.
When enabled, the prefab can use a groupPosition data field from the child group and apply child transforms more globally rather than purely relative to the prefab transform.
This is mainly a compatibility/special-case option. Most prefabs should leave it disabled.
When a prefab is loaded, the engine can track the prefab file for changes. If the file changes, the prefab reloads:
This helps when editing prefab files externally.
noAutoReload on the root SimGroup disables this behavior.
The engine prevents infinite recursion when loading prefabs.
For example, this is invalid:
Prefab A loads Prefab B
Prefab B loads Prefab A
If a prefab file is already in the active prefab loading stack, loading is stopped and an error is logged.
Legacy .prefab files are TorqueScript-based.
They are loaded by executing the file:
exec("path/to/file.prefab");
The file must create a SimGroup and assign it to $ThisPrefab.
Example:
$ThisPrefab = new SimGroup(GaragePrefabGroup) {
new TSStatic(garage_building) {
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";
};
};
If $ThisPrefab is not set or does not point to a valid SimGroup, the prefab fails to load.
.prefab files are still supported, but new content should prefer JSON prefabs where possible.When loading JSON prefabs, the engine performs special handling for BeamNGVehicle objects.
If a vehicle object specifies a jBeam/jbeam but does not specify partConfig, the engine attempts to load the vehicle’s info.json and use the default part configuration.
It may also fill in missing default paint data:
colormetallicPaintDataExample:
{
"class": "BeamNGVehicle",
"name": "display_vehicle",
"jBeam": "vivace",
"position": [0,0,0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1,1,1]
}
If the vehicle has a valid default configuration, missing fields may be completed automatically during load.
Not all objects are valid inside prefabs.
Valid objects are generally normal scene objects, static shapes, lights, groups, and similar placeable content.
The engine rejects or warns about several object types:
| Object type | Reason |
|---|---|
MissionGroup |
Prefabs should not contain the main mission group. |
LevelInfo |
Level-global object, not valid inside a prefab. |
TimeOfDay |
Level-global object, not valid inside a prefab. |
TerrainBlock |
Terrain is level-global and should not be inside a prefab. |
Player |
Player objects are not valid prefab children. |
Global-bounds SceneObjects |
Global objects are not valid prefab children. |
SimPath is explicitly allowed.
A prefab can be “exploded” or unpacked into normal scene objects.
When exploded:
The resulting group may receive fields such as:
| Field | Description |
|---|---|
unpacked_prefab |
Marks the group as unpacked from a prefab. |
prefab_filename |
Original prefab file path. |
prefab_name |
Original prefab object name. |
prefab_loadmode |
Original load mode. |
prefab_position |
Original prefab position. |
This allows tools to know that the group came from a prefab.
The engine includes support for converting older prefabs to a newer prefab representation (PrefabV2).
The conversion process roughly:
PrefabV2This is mostly handled by tools and editor workflows.
When saving a legacy prefab, the prefab saves its child SimGroup to the target file.
Legacy saving commonly uses a prefix such as:
$ThisPrefab =
This ensures that loading the .prefab file can recover the created root group.
For JSON workflows, prefer editor tools that serialize objects in the expected JSON format.
When a Prefab object is added to the scene:
loadMode is Automatic, load() is called.filename..json, JSON prefab loading is used.SimGroup is found.{
"class": "Prefab",
"name": "garage_prefab",
"filename": "/levels/example/prefabs/garage.json",
"loadMode": "Automatic",
"position": [100, 200, 0],
"rotationMatrix": [1,0,0,0,1,0,0,0,1],
"scale": [1,1,1]
}
{"class":"SimGroup","name":"garage_group"}
{"class":"TSStatic","name":"garage_building","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":[0,2,3],"rotationMatrix":[1,0,0,0,1,0,0,0,1],"scale":[1,1,1],"intensity":800}
.prefab
$ThisPrefab = new SimGroup(GaragePrefabGroup) {
new TSStatic(garage_building) {
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";
};
};
SimGroup.TerrainBlock, LevelInfo, or TimeOfDay.Automatic load mode for normal level content.Manual only when a tool or script controls loading.Possible causes:
filenameSimGroup.prefab does not set $ThisPrefabA prefab references itself directly or indirectly. Remove the circular reference.
Possible causes:
useGlobalTranslationgroupPosition data fieldThe file is being tracked for changes. Use noAutoReload on the root SimGroup if automatic reload should be disabled.
The object may be invalid for prefabs, such as TerrainBlock, LevelInfo, TimeOfDay, Player, or a global-bounds object.
Prefabs are reusable object groups stored outside the main level file.
Modern JSON prefabs contain a root SimGroup and one or more child objects. The Prefab scene object loads the file, manages child transforms, updates children when moved, and can reload when the file changes.
Legacy .prefab files are still supported, but new content should use JSON prefab workflows where possible.
Was this article helpful?