RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Reference

Server CommandsGE UtilitiesGame Engine MainNavigation GraphScreenshot CaptureServerServer ConnectionSpawnpoint ManagerSimulation TimeVehicle SpawningSuspension Frequency Tester
Gameplay AchievementGameplay CityDiscoverForce FieldGarage ModeMarker InteractionParking SystemGameplay Playmode MarkersGameplay PoliceGameplay RallyGameplay Rally LoopGameplay Raw POIsGameplay Skidpad TestSpeed Trap LeaderboardsSpeed Traps and CamerasGameplay StatisticsTaxi Ride SystemTraffic SystemVehicle PerformanceWalking

UI

Resources

BeamNG Game Engine Lua Cheat SheetGE Developer RecipesMCP Server Setup

// RLS.STUDIOS=true

Premium Mods for BeamNG.drive. Career systems, custom vehicles, and immersive gameplay experiences.

Index

HomeProjectsPatreon

Socials

DiscordPatreon (RLS)Patreon (Vehicles)

© 2026 RLS Studios. All rights reserved.

Modding since 2024

API ReferenceGE Extensionsgameplay

Gameplay Statistics

Reference for `gameplay_statistic`, the central metrics engine that records, persists, and reports gameplay statistics. Supports both global and career-scoped data with timers, callbacks, and a schedu

Reference for gameplay_statistic, the central metrics engine that records, persists, and reports gameplay statistics. Supports both global and career-scoped data with timers, callbacks, and a scheduling system for per-frame stat modules.


Module Exports (M)

Metrics

FunctionSignatureDescription
metricAdd(name, value, aggregate?)Adds value to the metric (cumulative). Optional aggregate tracks min/max/count/last
metricSet(name, value, aggregate?)Sets metric to value. Optional aggregate tracks min/max/count
metricGet(name, career?) → table|nilReturns a deep copy of the metric entry. Pass true for career data

Timers

FunctionSignatureDescription
timerStart(name, increment?, aggregate?, useSimTime?)Starts a named timer. increment=true adds to existing value
timerStop(name) → numberStops the timer and writes elapsed time as a metric
forceTimerUpdate()Flushes all active timers to their metrics

Callbacks

FunctionSignatureDescription
callbackRegister(name, trigger, func, career?)Registers a callback when metric name reaches trigger value
callbackRemove(name, trigger, func, career?) → boolRemoves a registered callback

Schedule

FunctionSignatureDescription
addSchedule(fn)Adds a per-frame workload function (called round-robin)
removeSchedule(fn) → boolRemoves a scheduled function

UI & Debug

FunctionSignatureDescription
sendGUIState()Sends all stats to UI via StatisticData guihook
setDebug(bool)Opens/closes the ImGui debug window

Hooks / Lifecycle

FunctionDescription
onInitLoads global stats from JSON
onExitFlushes timers and saves
onExtensionUnloadedFlushes timers and saves
onExtensionLoadedLoads statistic submodules
onSerializeSaves data and returns state for hot-reload
onDeserializedRestores state after hot-reload
onSaveCurrentSaveSlotSaves career stats into save slot
onCareerActiveLoads/unloads career-specific stats
onClientStartMissionStarts activity timer for current level
onClientEndMissionEnds current activity timer
onClientPostStartMissionStarts activity and loads submodules
onWorldReadyStateWorld ready callback (currently unused)
onEditorActivatedStarts editor timer
onEditorDeactivatedStops editor timer
onScenarioLoadedRestarts activity tracking
onScenarioFinishedRecords scenario completion metric
onScenarioRestartedRecords scenario restart metric
onUpdateIncrements timers, runs scheduled workloads, renders debug UI
onVehicleSwitchedTracks player vehicle change, records switch metric
onVehicleResettedRecords vehicle reset metric
onVehicleDestroyedClears player vehicle reference
onGameStateUpdateRestarts activity tracking on game state change
M.addSchedule(fn)
M.callbackRegister(name, trigger, callbackFunction, career)
M.callbackRemove(name, trigger, callbackFunction, career)
M.dependenciesvalue
M.forceTimerUpdate()
M.metricAdd(name,value,aggregate)
M.metricGet(name, carreer)
M.metricSet(name,value,aggregate)
M.onCareerActive(active)
M.onClientEndMission(levelPath)
M.onClientPostStartMission(levelPath)
M.onClientStartMission(levelPath)
M.onDeserialized(data)
M.onEditorActivated()
M.onEditorDeactivated()
M.onExit()
M.onExtensionLoaded()
M.onExtensionUnloaded()
M.onGameStateUpdate(newState)
M.onInit()
M.onSaveCurrentSaveSlot(currentSavePath)
M.onScenarioFinished(scenario)
M.onScenarioLoaded(scenario)
M.onScenarioRestarted(scenario)
M.onSerialize()
M.onUpdate(dtReal, dtSim, dtRaw)
M.onVehicleDestroyed(vid)
M.onVehicleResetted(vid)
M.onVehicleSwitched(oldid, newid, player)
M.onWorldReadyState(worldReadyState)
M.removeSchedule(fn)
M.sendGUIState()
M.setDebug(newValue)
M.timerStart(name, increment, aggregate, useSimTime)
M.timerStop(name)

Internals

  • Save file (global): /settings/cloud/gameplay_stat.json
  • Save file (career): <saveslot>/career/gameplay_stat.json
  • Format: {version = 1, entries = {[name] = {value, count?, min?, max?, last?}}}
  • Dual storage: Every metricAdd/metricSet call writes to both global and career data (if career active)
  • Scheduling: Submodules from gameplay/statisticModules/ are loaded dynamically; their workload function is called round-robin each frame (one module per frame)

Metric Entry Format

{
  value = 42.5,     -- accumulated/current value
  last = 2.1,       -- last added value (aggregate only)
  count = 10,       -- number of additions (aggregate only)
  min = 0.5,        -- minimum value seen (aggregate only)
  max = 8.3         -- maximum value seen (aggregate only)
}

How It Works

  1. On init, loads global stats from JSON file
  2. On career activation, loads career-specific stats from save slot
  3. onClientPostStartMission starts activity timers and loads submodules
  4. onUpdate increments real/sim timers and calls one scheduled workload per frame
  5. Activity tracking auto-categorizes time by mode (freeroam/career/scenario) and level
  6. Callbacks fire when a metric reaches a threshold; one-shot callbacks auto-remove

Usage Example

-- Track a gameplay event
gameplay_statistic.metricAdd("vehicle/burnout.time", dtSim, true)

-- Read a stat
local data = gameplay_statistic.metricGet("vehicle/jturn", true) -- career
if data then
  log("I", "", "J-turns in career: " .. data.value)
end

-- Timer usage
gameplay_statistic.timerStart("myMod/lapTime", false, false, true) -- sim time, non-increment
-- ... later ...
local elapsed = gameplay_statistic.timerStop("myMod/lapTime")

-- Register a callback
gameplay_statistic.callbackRegister("vehicle/rollover", 5, function(name, old, new)
  log("I", "", "5 rollovers reached!")
end, true) -- career-scoped

See Also

  • Gameplay Achievement - Related reference
  • Gameplay City - Related reference
  • discover - Discover / Experience System - Related reference
  • Gameplay Systems Guide - Guide

Speed Traps and Cameras

Reference for `gameplay_speedTraps`, which handles speed trap and red light camera trigger events. Fires visual flash effects and dispatches hooks when vehicles exceed speed limits.

Taxi Ride System

Reference for `gameplay_taxi`, which manages the full taxi ride experience - finding nearby taxis, hailing, entering, choosing a destination via the big map, AI-driven travel, idle camera, skip/telepo

On this page

Module Exports (M)MetricsTimersCallbacksScheduleUI & DebugHooks / LifecycleInternalsMetric Entry FormatHow It WorksUsage ExampleSee Also