Actions

Overview

An Action is each of the in-game activities that can take place after the player has manipulated a Control .

E.g. steer left, change camera, toggle menu.

Actions are defined in one or more .json files.

It is possible to provide new extra actions through mods. Just remember that, if you don’t also provide some bindings, then the users of your mod will need to manually configure his controllers.

There are two basic kinds of actions: Regular actions and Vehicle-specific actions :

Regular Actions

Regular actions are those that can take place regardless of which vehicle is currently used.

They can therefore be available for use even while in the main menu, before entering any level or spawning any vehicle.

BeamNG.drive comes with many predefined regular actions. These are defined in:

lua/ge/extensions/core/input/actions/*.json

Mods can bundle additional regular actions. To do so, they must provide one or more additional json files following this naming convention:

lua/ge/extensions/core/input/actions/*.json

For example:

lua/ge/extensions/core/input/actions/explosions_mod.json
lua/ge/extensions/core/input/actions/advanced_menus.json

Any actions defined there will be available to end-users in the OptionsControls menu, mixed in with the default actions provided by BeamNG.drive.

While it is possible to override the default input_actions.json file with a customized one, this means the mod author will need to constantly update his modified file each time a BeamNG.drive update comes out with new actions (or modified actions, or removed ones). It is therefore strongly advised against.

Vehicle-specific Actions

Vehicle-specific actions are those that can only be triggered while driving an specific vehicle. If you switch to a different kind of vehicle, they’ll be replaced by the actions of the new vehicle.

Some of BeamNG.drive official vehicles come with a few predefined vehicle-specific actions. For example, the Small Cannon provides the ability to open fire with your controller. These vehicle-specific actions are defined in:

vehicles/vehicle_directory_name/input_actions.json

Similarly to Regular actions , mods can bundle additional vehicle-specific actions too. The mod-provided files must follow this naming convention:

vehicles/vehicle_directory_name/input_actions*.json

For example:

vehicles/hatch/input_actions_hydraulic_suspension.json
vehicles/pickup/input_actions_winch_cable.json

All of these actions will be typically found in the “Vehicle-specific” category of the OptionsControls menu.

Again, it is necessary to use unique file names for your vehicle-specific actions, to make sure your actions are not overridden by other mods using the same file names.

Action-files Format

Action files mostly follow the json format . They must start with { and end with }. Here’s a sample of how the overall structure has to look like:

{
    "an_action"     : {"order":1,  "title":"Do Something", ...},
    "another_action": {"order":2,  "title":"Do Something Else", ...},
    "third_action"  : {"order":10, "title":"Do More Things", ...},
    //...
}

Each line has two parts:

  • The first string on each line is the action name. E.g. "an_action".
  • The rest of the line contains the parameters of the action. E.g. "order", "title", "ctx", and more.

Here’s more information about them:

Action names

Action names must be unique, otherwise they may get overridden by other mods using the same action names. Specifically:

  • Regular action names must be different from all other regular actions names.
  • Vehicle-specific action names must be unique within the current vehicle.

The easiest way to ensure the action names are unique, is to use a unique prefix. For example:

{
    "extra-menus-mod_an_action"     : { ... },
    "extra-menus-mod_another_action": { ... },
    "extra-menus-mod_third_action"  : { ... },
    //...
}

Action Parameters

The parameters of an action controls what the action actually does and how it’s displayed in the menus. Here’s a table with all details:

Vehicle-specific actions have some particularities, which are also described below

Name
Mandatory
Type
Default Value
Description
Name
title
Mandatory
Yes
Type
string
Default Value
n/a
Description
Very short name of the action, will be displayed in various game menues
Name
desc
Mandatory
Yes
Type
string
Default Value
n/a
Description
Full description, may be displayed as tool-tip, should be about one sentence long.
Name
isBasic
Mandatory
No
Type
boolean
Default Value
true
Description
Whether it is shown by default in the Controls > Binding menu (true) or user needs to check “List advanced bindings too” (false)
Name
cat (regular actions)
Mandatory
Yes
Type
string
Default Value
n/a
Description
Name
cat (vehicle-specific actions)
Mandatory
No
Type
string
Default Value
“vehicle_specific”
Description
Name
order
Mandatory
Yes
Type
number
Default Value
n/a
Description
Can influence in which order actions are displayed on various UI menus, with 1 coming first, and larger values (2, 3…) coming later.
Name
isCentered
Mandatory
No
Type
boolean
Default Value
false
Description
If false, the action will produce values in the range 0 to 1 (for example, it can be used for a brake pedal or handbrake). If true, generated values will be in the range of -1 to +1 (for example, it can be used for the steering, or for changing the camera height up and down).
Name
actionMap (regular actions)
Mandatory
No
Type
string
Default Value
“Normal”
Description

Determines which Action Map the action will be assigned into. Common action maps include:

  • “Global” - works even when the UI has focus; use sparingly
  • “Menu” - assigned automatically when cat is menu
  • “Normal” - default map for normal gameplay bindings
  • “VehicleCommon” - assigned automatically when ctx is vlua
  • “VehicleSpecific” - assigned automatically for vehicle-specific action files

Custom names can be specified, and the corresponding action map will be automatically created.

Name
actionMap (vehicle-specific actions)
Mandatory
No
Type
string
Default Value
“VehicleSpecific”
Description
Determines which Action Map the action will be assigned into. Most vehicle-specific actions should use the default.
Name
ctx (regular actions)
Mandatory
No
Type
string
Default Value
“tlua”
Description

Defines where the code in onChange, onUp, onDown, or onRelative runs:

  • “tlua” for Game Engine Lua (default for regular actions)
  • “vlua” for active vehicle Lua
  • “bvlua” for all vehicle Lua contexts
  • “elua” for asynchronous Game Engine Lua / legacy-special cases

Deprecated contexts: “ui”, “ts”, and “slua”.

Name
ctx (vehicle-specific actions)
Mandatory
No
Type
string
Default Value
“vlua”
Description
See the description above
Name
  • onChange
  • onDown
  • onUp
  • onRelative
Mandatory
Yes
Type
string
Default Value
n/a
Description

Specifies which source code will be executed when the action is triggered. The code execution context is defined in the ctx parameter of the current action

At least one of them must be defined. They are triggered like this:

  • onChange: runs when the controller position changes. Supports: keys/buttons and axes
  • onDown: runs when a key/button is pressed down. Supports: keys/buttons
  • onUp: runs when a key/button is lifted up. Supports: keys/buttons
  • onRelative: runs when holding the right mouse button and moving the mouse (don’t use unless you know what you’re doing)

Writing Action Code

The onChange, onDown, onUp, and onRelative fields contain short code snippets.

They are not a separate scripting language. They are strings that contain Lua code, with a few special placeholder words replaced by the input system before the code is executed.

Example:

{
  "my_mod_toggle": {
    "cat": "vehicle",
    "order": 10,
    "ctx": "vlua",
    "onDown": "controller.getControllerSafe('myController').toggle()",
    "title": "My Mod Toggle",
    "desc": "Toggles a feature from my mod"
  }
}

The action definition does two jobs:

  1. Describes how the action appears in the Controls menu.
  2. Provides code that runs when a binding triggers the action.

Action event fields

Field When it runs Typical use
onChange Whenever the input value changes. Works with keys/buttons and axes. Analog controls, held buttons, values that should follow input.
onDown When a key/button is pressed. Toggles, one-shot commands, mode changes.
onUp When a key/button is released. Releasing held state, momentary controls.
onRelative For relative input such as mouse movement where supported. Camera/mouse style controls.

At least one of these fields must be present.

Use onChange for axes and analog controls. Use onDown for simple button toggles.

Do not rely on onDown or onUp for axis-only controls. Axes should use onChange.

Placeholder values

Before the action code is run, the input system replaces special placeholder words.

Common placeholders:

Placeholder Meaning
VALUE Current input value. Usually 1 on press, 0 on release, 0..1 for normal analog inputs, or -1..1 when isCentered is true.
FILTERTYPE Selected input filter type from the binding. Used by vehicle input functions.
PLAYER Player index for multiseat-aware actions.
ANGLE Steering wheel angle data where supplied by the binding/device.
LOCKTYPE Steering lock type where supplied by the binding/device.
OSCLOCKHP High precision timestamp used by some input paths.

Programmatic action triggering can also replace:

Placeholder Meaning
VEHICLEID Vehicle id passed to the action trigger helper.

Example:

{
  "set_table": {
    "order": 1,
    "ctx": "vlua",
    "onChange": "electrics.values.table = VALUE",
    "title": "Move Table",
    "desc": "Moves the table with an analog input"
  }
}

With a centered control:

{
  "move_platform": {
    "order": 1,
    "ctx": "vlua",
    "isCentered": true,
    "onChange": "controller.getControllerSafe('platform').move(VALUE)",
    "title": "Move Platform",
    "desc": "Moves the platform in both directions"
  }
}

isCentered changes the value range from 0..1 to -1..1.


Execution context

The ctx field decides where the code runs.

ctx Runs in Common use
tlua Game Engine Lua. Default for regular actions. UI/gameplay systems, global commands, editor/tool actions.
vlua Active vehicle Lua. Default for vehicle-specific actions. Vehicle controllers, electrics, powertrain, hydros, vehicle extensions.
elua Game Engine Lua asynchronous path. Legacy/special cases. Prefer tlua for normal GE Lua actions.
bvlua All vehicle Lua contexts. Broadcast a vehicle Lua command to all vehicles.

Deprecated contexts:

ctx Status
ui Deprecated. Use tlua and guihooks instead.
ts Deprecated. Use tlua instead.
slua Deprecated alias that is replaced with elua.

If no ctx is specified for a regular action, the input system defaults to tlua. Vehicle-specific actions default to vlua.


Choosing a context

Use vlua when the action controls the current vehicle:

"onChange": "input.event('throttle', VALUE, FILTERTYPE)",
"ctx": "vlua"

Use tlua when the action controls game systems, UI, editor tools, or global gameplay:

"onDown": "extensions.hook('onGameplayInteract')",
"ctx": "tlua"

Use bvlua only when every vehicle should receive the command:

"onDown": "electrics.set_warn_signal(true)",
"ctx": "bvlua"

Do not call vehicle-only APIs from tlua, and do not call game-engine UI systems directly from vlua.


actionMap

actionMap controls which action map receives the binding.

Default behavior:

Condition Action map
cat is menu MenuActionMap
ctx is vlua VehicleCommonActionMap
vehicle-specific action VehicleSpecificActionMap
otherwise NormalActionMap

You can override this with:

"actionMap": "BigMap"

The final scene object name is the action map name plus ActionMap, for example:

BigMapActionMap

Special case:

"actionMap": "MenuIndependent"

This creates a per-action menu-independent action map using the MenuIndependent_ prefix.


Regular action example

This regular action runs in Game Engine Lua and toggles a custom UI/tool feature:

{
  "my_mod_toggle_tool": {
    "cat": "menuExtra",
    "order": 900,
    "ctx": "tlua",
    "actionMap": "Normal",
    "onDown": "extensions.my_mod_tool.toggle()",
    "title": "Toggle My Tool",
    "desc": "Opens or closes my custom tool"
  }
}

Suggested location:

lua/ge/extensions/core/input/actions/my_mod_actions.json

Use a unique file name and unique action names to avoid conflicts with other mods.


Vehicle-specific action example

This vehicle-specific action writes a value to the vehicle electrics table:

{
  "raise_arm": {
    "order": 1,
    "onChange": "electrics.values.arm = VALUE",
    "title": "Raise Arm",
    "desc": "Raises the vehicle arm"
  }
}

Suggested location:

vehicles/<vehicleName>/input_actions_my_mod.json

Vehicle-specific actions automatically:

  • get namespaced internally to the current vehicle
  • default to ctx = "vlua"
  • appear in the vehicle-specific controls category

JBeam event actions

Some vehicle parts define trigger/action data directly in JBeam events sections.

Example:

"events": [
  ["id", "title", "desc"],
  ["table_up", "ui.inputActions.tiltdeck.table_up.title", "ui.inputActions.tiltdeck.table_up.description",
    { "onChange": "electrics.values.table = VALUE", "order": 6 }
  ]
]

The action code uses the same onChange, onDown, onUp, and placeholder behavior as input_actions.json.

Use this when the action belongs tightly to a part or trigger setup. Use input_actions*.json when the action is a normal vehicle-level binding.


Interaction maps

Vehicle interaction maps using *.interaction.json also use the same action-code format.

They are useful for interactions such as doors, latches, vehicle features, or part-specific controls that need to appear in the interaction UI.

See Interaction Maps and the vehicle trigger/interaction documentation for examples.


Best practices

  • Use onDown for toggles.
  • Use onChange for analog values and held controls.
  • Keep action snippets short.
  • Put complex behavior in a Lua module or controller function, then call that function from the action.
  • Use translation keys for title and desc when shipping user-facing content.
  • Use unique action names and unique file suffixes for mods.
  • Provide default bindings for vehicle-specific actions when possible.
  • Avoid deprecated contexts (ui, ts, slua).
  • Test actions with keyboard and at least one analog device if the action supports analog input.

Common issues

Action does not appear in Controls

Possible causes:

  • JSON file is in the wrong folder.
  • JSON syntax error.
  • Duplicate action name was overridden.
  • Invalid category.
  • Vehicle-specific action is not active for the current vehicle.

Binding appears but does nothing

Possible causes:

  • Action has no onChange, onDown, onUp, or onRelative.
  • Wrong ctx was used.
  • Code calls a Lua module that is not loaded in that context.
  • Vehicle-specific controller name is wrong.

Analog control behaves like a button

Possible causes:

  • Action uses onDown instead of onChange.
  • isCentered is missing for a centered axis.
  • Binding filter type is not appropriate.

Action Categories

The category of an action is a mandatory parameter with only cosmetic effects.

It will influence where the action may be displayed in various in-game menus (such as the OptionsControls hierarchy of actions).

To see a list of available categories, please refer to the following file:

lua/ge/extensions/core/input/categories.lua
Last modified: June 8, 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.