RLS Studios
ProjectsPatreonCommunityDocsAbout
Join Patreon
BeamNG Modding Docs

Guides

Your First BeamNG ModMod Scripts (modScript.lua)Creating a GE ExtensionLoading Extension Folders

Reference

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

GuidesGetting Started

Mod Scripts (modScript.lua)

How modScript.lua works — the entry point for your mod that controls which extensions persist across level changes.

Without a mod script, your extensions vanish every time the player switches maps. The mod script (modScript.lua) is loaded before anything else in your mod — it tells the engine which extensions should stay alive across level changes, career transitions, and map switches.


What is a Mod Script?

Every mod should have a modScript.lua file. The mod manager (core_modmanager) discovers and executes these files during initialization, before any extensions are loaded. This is where you:

  1. Register your extensions with setExtensionUnloadMode
  2. Call loadManualUnloadExtensions() to load them

File Location

your_mod.zip (or mods/unpacked/your_mod/)
  scripts/
    your_mod_name/
      modScript.lua        <-- This file
  lua/
    ge/
      extensions/
        your_mod_name/
          feature.lua      <-- Your extensions
          ui.lua
          data.lua

The mod script lives at scripts/<your_mod_name>/modScript.lua. The game scans /scripts/ for all modScript.lua files recursively.


Basic Mod Script

-- scripts/mymod/modScript.lua

-- Register extensions that should persist across level changes
setExtensionUnloadMode("mymod_feature", "manual")
setExtensionUnloadMode("mymod_ui", "manual")
setExtensionUnloadMode("mymod_data", "manual")

-- Load all registered manual-unload extensions
loadManualUnloadExtensions()

That's it. This ensures your extensions are loaded early and stay loaded when the player switches maps or enters/exits career.


How It Works Internally

The mod manager does the following when loading mod scripts:

  1. Finds all modScript.lua files in /scripts/ (recursively)
  2. Executes each one with dofile()
  3. During execution, setExtensionUnloadMode(name, "manual") registers the extension name in a manual-unload list
  4. loadManualUnloadExtensions() calls extensions.load() on everything in that list
  5. These extensions will NOT be unloaded during level transitions

The mod manager also temporarily wraps extensions.load() during modScript execution so that any extensions loaded directly also get marked as manual.


Real-World Example

Here's how a mod with multiple systems would set up its mod script:

-- scripts/mymod/modScript.lua

-- Core systems (always loaded)
setExtensionUnloadMode("mymod_core", "manual")
setExtensionUnloadMode("mymod_config", "manual")

-- Feature modules
setExtensionUnloadMode("mymod_economy", "manual")
setExtensionUnloadMode("mymod_missions", "manual")
setExtensionUnloadMode("mymod_vehicles", "manual")

-- UI extensions
setExtensionUnloadMode("mymod_phone", "manual")
setExtensionUnloadMode("mymod_hud", "manual")

-- Load everything
loadManualUnloadExtensions()

The Extensions

-- lua/ge/extensions/mymod/core.lua
-- Extension name: mymod_core

local M = {}

local function onExtensionLoaded()
  log('I', 'mymod', 'Core system loaded')
end

local function onExtensionUnloaded()
  log('I', 'mymod', 'Core system unloaded')
end

M.onExtensionLoaded = onExtensionLoaded
M.onExtensionUnloaded = onExtensionUnloaded

return M

Note: The extension itself does NOT call setExtensionUnloadMode. That's handled by the mod script.


Important Rules

:::danger[Critical Mistake] Do NOT put setExtensionUnloadMode inside your extension. It must go in modScript.lua. :::

Do NOT use onInit for setExtensionUnloadMode

-- WRONG - don't do this
M.onInit = function()
  setExtensionUnloadMode(M, "manual")
end
-- RIGHT - do this in modScript.lua instead
setExtensionUnloadMode("mymod_feature", "manual")
loadManualUnloadExtensions()

The mod script runs before extensions are loaded, ensuring everything is set up in the correct order.

Always call loadManualUnloadExtensions()

Without this call, your setExtensionUnloadMode registrations don't actually load anything. This is the function that triggers the actual loading.

Extension names match file paths

Remember the naming convention:

lua/ge/extensions/mymod/feature.lua  ->  mymod_feature
lua/ge/extensions/mymod/ui/phone.lua ->  mymod_ui_phone

Use these exact names in your setExtensionUnloadMode calls.


Mod Script vs Extension Loading

ApproachWhen to Use
modScript.lua + setExtensionUnloadModeYour main mod extensions that need to persist
extensions.load() at runtimeDynamic loading (e.g., loading a feature only when needed)
loadModulesInDirectory()Loading an entire folder of sub-modules

Most mods should use the mod script for their core extensions. Use runtime loading only for optional features that don't need to be always active.


Discovery Order

  1. Game starts, loads lua/ge/main.lua
  2. Core extensions load (engine internals)
  3. core_modmanager initializes
  4. Mod manager scans /scripts/*/modScript.lua
  5. Each modScript executes (registers extensions)
  6. loadManualUnloadExtensions() loads all registered extensions
  7. Extensions receive onExtensionLoaded callbacks
  8. Game is ready

Your mod script runs at step 4-6, which is early enough that your extensions are available before any gameplay starts.


Debugging Mod Scripts

If your mod script fails to load, check the console for:

[E] initDB.modScript - Failed to execute scripts/mymod/modScript.lua

Common issues:

  • Wrong file path (must be in scripts/<name>/modScript.lua)
  • Typo in extension name (must match the file path exactly)
  • Missing loadManualUnloadExtensions() call
  • Extension file doesn't exist at the expected path

See Also

  • Getting Started - First mod setup
  • Creating Extensions - Extension reference
  • Module Loading - Loading folders of extensions
  • Boot Sequence - Full startup order
  • Mod Loading - How mods are discovered and mounted

Your First BeamNG Mod

Step-by-step guide to creating your first BeamNG.drive Lua mod — file structure, extensions, hooks, and UI communication.

Creating a GE Extension

Step-by-step guide to creating a GE extension — file naming, lifecycle hooks, dependencies, and the full loading sequence.

On this page

What is a Mod Script?File LocationBasic Mod ScriptHow It Works InternallyReal-World ExampleThe ExtensionsImportant RulesDo NOT use onInit for setExtensionUnloadModeAlways call loadManualUnloadExtensions()Extension names match file pathsMod Script vs Extension LoadingDiscovery OrderDebugging Mod ScriptsSee Also