User Tools

Site Tools


manual:subwaysim:vehicle_development:vehicle_lua

This is an old revision of the document!


Creating a Simple Vehicle.lua

This page explains how to create a simple `vehicle.lua` file, primarily intended for AI-controlled trains in SubwaySim 2.

A simple `vehicle.lua` usually defines:

  • Vehicle metadata (name, author, IDs)
  • Basic physical parameters (mass, length, vmax)
  • Blueprint references
  • Coupling definitions
  • Braking systems
  • Basic lights and audio
  • Train compositions for AI

For a detailed explanation of a fully featured and player-drivable vehicle, see:


Example Vehicle.lua (AI Vehicle)

The following example is based on the GI1E (Gisela) AI vehicle used in the SubwaySim base game.

Because the original file is not publicly downloadable, the full structure is shown below and explained step by step in separate sections.

vehicle.lua
---@type RailVehicle_DataTable
local GI1E_a = {
	contentType		= "railVehicle",
	contentName		= "Berlin_GI1E_a",
 
	title			= "GI1E",
	author			= "$GameDeveloper",
 
	emptyMass			= 37.0,
	vmax				= 70,
 
	length				= 12.64,
	frontToFirstBogie	= 2.53,
	rearToLastBogie		= 2.53,
 
	maxEnginePower		= 480,
	maxEngineForce		= 50,
 
	blueprintFilename	= "/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_A.BP_GI1E_A",
 
	couplingFront		= {
		rotationOrigin		= "Coupling_F",
		couplingOffset		= 0.985,
		automaticCoupling	= true,
		skeletalMesh		= "Exterior",
		couplingBoneName	= "Coupling_Rotation1",
	},
	couplingRear		= {
		rotationOrigin		= "Coupling_B",
		couplingOffset		= 0.985,
		automaticCoupling	= true,
		skeletalMesh		= "Exterior",
		couplingBoneName	= "Coupling_Rotation2",
	},
 
	-- players shouldn't try to attach this vehicle
	cameras				= {
		exteriorCameras	= {},
	},
 
	brakingSystems		= {
		pneumatic5bar	= {
			maxBrakeForce	= 60,
		},
		electric		= {
			maxBrakeForce	= 50,
			maxBrakePower	= 480,
		},
	},
 
	components = {
		LightManager,
		VehicleNumber,
		AudioManager,
		Berlin_PIS,
	},
 
	audio = {
		audioBogieAI = {
			{
				audioComponent = "AiAudio",
			},
		},
	},
 
	lights = {
		headLights = {
			{
				direction			= 1,
				headlightElements	= {
					{
						mesh			= "Exterior",
						materialSlot	= "GI1E_LightsExterior_mat",
						materialParams	= {
							["Emissive01"] = 100,
						},
						lightComponents	= {
							{lightComponent ="Headlight1", intensity = 50, temperature = 4500, attenuationRadius = 500, innerConeAngle = 0, outerConeAngle = 70},
							{lightComponent ="Headlight2", intensity = 50, temperature = 4500, attenuationRadius = 500, innerConeAngle = 0, outerConeAngle = 70},
						},
					},
				},
			},
		},
		tailLights = {
			{
				mesh			= "Exterior",
				materialSlot	= "GI1E_LightsExterior_mat",
				direction		= -1,
				materialParams	= {
					["Emissive02"] = 100,
				},
			},
		},
	},
 
	---@type Berlin_PIS_DataTable
	PIS = {
		destinationDisplays	= {
			{
				componentName	= "ZZA",
				direction		= 1,
			},
		},
 
		announcementNextStop		= {},
		announcementTerminus		= {
			"/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/General_Termination01.General_Termination01",
		},
		announcementExitLeft		= {},
		announcementExitRight		= {
			"/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/General_ExitRight.General_ExitRight",
		},
		announcementBell			= {
			"/SubwaySim_Berlin/Vehicles/Shared/Audio/Gong/Berlin_Standardgong_MasterV1_kurz.Berlin_Standardgong_MasterV1_kurz",
		},
		announcementTerminusBell	= {
			"/SubwaySim_Berlin/Vehicles/Shared/Audio/Gong/Berlin_Infogong_MasterV2_kurz.Berlin_Infogong_MasterV2_kurz",
		},
		announcementDelay					= 1.2,
		defaultDestinationAnnouncement		= "/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/Destination_General.Destination_General",
		destinationAnnouncementByLine		= {
			["U1"]	= "/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/Destination_U1.Destination_U1",
			["U2"]	= "/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/Destination_U2.Destination_U2",
			["U3"]	= "/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/Destination_U3.Destination_U3",
			["U4"]	= "/SubwaySim_Berlin/Vehicles/Shared/Audio/Announcements/Destination_U4.Destination_U4",
		},
 
		audioComponent				= "PIS_Audio",
		autoTerminateAnnouncement	= false,
	},
 
	vehicleNumber = {
		labels	= {
			{
				mesh			= "Exterior",
				materialSlot	= "DecalDigits_mat",
			},
		},
		poolName		= "Berlin_GI1E",
		poolValueMin	= 1070,
		poolValueMax	= 1094,
	},
};
 
---@type RailVehicle_DataTable
local GI1E_b 								= TableUtil.deepCopy(GI1E_a);
GI1E_b.components 							= GI1E_a.components; -- TODO
GI1E_b.contentName 							= "Berlin_GI1E_b";
GI1E_b.blueprintFilename 					= "/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_B.BP_GI1E_B";
GI1E_b.lights.headLights					= nil;
GI1E_b.lights.tailLights					= nil;
GI1E_b.couplingFront.couplingBoneName		= "Coupling_Rotation3";
GI1E_b.couplingRear.couplingBoneName		= "Coupling_Rotation4";
 
---@type TrainComposition_DataTable
local GI1E_1x = {
	contentType		= "trainComposition",
	contentName		= "Berlin_GI1e_1x",
 
	title			= "GI1e x1",
	author			= "Simuverse GmbH",
 
	-- not required for AI trains
	description			= "",
	previewFilename 	= "",
	hidden 				= true,
 
	vehicles		= {
		{
			contentName	= "Berlin_GI1E_a",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= false,
		},
		{
			contentName	= "Berlin_GI1E_a",
			forward		= false,
		},
	},
};
 
---@type TrainComposition_DataTable
local GI1E_2x = {
	contentType		= "trainComposition",
	contentName		= "Berlin_GI1e_2x",
 
	title			= "GI1e x2",
	author			= "Simuverse GmbH",
 
	-- not required for AI trains
	description			= "",
	previewFilename 	= "",
	hidden 				= true,
 
	vehicles		= {
		{
			contentName	= "Berlin_GI1E_a",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= false,
		},
		{
			contentName	= "Berlin_GI1E_a",
			forward		= false,
		},
		{
			contentName	= "Berlin_GI1E_a",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= true,
		},
		{
			contentName	= "Berlin_GI1E_b",
			forward		= false,
		},
		{
			contentName	= "Berlin_GI1E_a",
			forward		= false,
		},
	},
};
 
g_contentManager:addContent(GI1E_a);
g_contentManager:addContent(GI1E_b);
g_contentManager:addContent(GI1E_1x);
g_contentManager:addContent(GI1E_2x);

RailVehicle_DataTable Explained

Now we will go through the `RailVehicle_DataTable` step by step.

The `RailVehicle_DataTable` contains the core configuration of a vehicle. It defines all information required so the game can correctly:

  • load the vehicle Blueprint,
  • place the vehicle on the track,
  • apply physics and braking,
  • configure couplings,
  • and register audio, lights, and additional Lua components.

In this example, the DataTable is stored in a local Lua table called `GI1E_a`.


Creating the Vehicle Data Table

---@type RailVehicle_DataTable
local GI1E_a = {
Entry Explanation
`local GI1E_a = {` Creates a local Lua table called `GI1E_a`. This table holds all vehicle data and will later be registered via the Content Manager.

Basic Metadata

These fields define what the vehicle is and how it appears inside the content system.

Entry Explanation
`contentType = “railVehicle”` Defines the content type. For vehicles, this must be `railVehicle`.
`contentName = “Berlin_GI1E_a”` Internal unique identifier used by the Content Manager. Must be unique across all loaded content.
`title = “GI1E”` Display name of the vehicle.
`author = “$GameDeveloper”` Author name shown in content information. You can replace this with your name/project.
`description = ““` Optional description text. Not required for AI-only trains.
`previewFilename = ”“` Optional preview image path. Not required for AI-only trains.

Physical Parameters

These values define physical base properties and basic performance.

Entry Explanation
`emptyMass = 37.0` Empty mass of the vehicle in tons.
`vmax = 70` Vehicle maximum speed (km/h) that the vehicle can reach by its own traction.

Dimensions and Bogie Distances

These values are critical for correct placement on the track and correct bogie positioning.

Entry Explanation
`length = 12.64` Total vehicle length from coupling tip to coupling tip (meters).
`frontToFirstBogie = 2.53` Distance from the front coupling tip to the center of the front bogie (meters).
`rearToLastBogie = 2.53` Distance from the rear coupling tip to the center of the rear bogie (meters).

Traction / Engine Settings

These values define the maximum propulsion capability of the vehicle.

Entry Explanation
`maxEnginePower = 480` Maximum engine power (kW). If you have multiple motors per car, sum them up for the full carbody.
`maxEngineForce = 50` Maximum tractive effort / force (kN).

Blueprint Reference

This defines which Unreal Blueprint is loaded for this vehicle.

Entry Explanation
`blueprintFilename = ”/SubwaySim_Berlin/Vehicles/GI1E/BP_GI1E_A.BP_GI1E_A”` Unreal asset path to the Vehicle Blueprint. Important: Unreal requires the Blueprint name twice at the end, without `.uasset`. Example: `/MyMod/Vehicles/TestTrain/BP_TestTrain.BP_TestTrain`

Coupling Configuration

This section is crucial for:

  • correct vehicle placement on the rail,
  • correct coupling rotation,
  • automatic coupling behavior in consists.

The front coupling:

couplingFront = {
    rotationOrigin     = "Coupling_F",
    couplingOffset     = 0.985,
    automaticCoupling  = true,
    skeletalMesh       = "Exterior",
    couplingBoneName   = "Coupling_Rotation1",
},
Entry Explanation
`rotationOrigin` Name of the Scene Component in your Vehicle Blueprint that defines the front coupling reference point (e.g. `Coupling_F`).
`couplingOffset` Offset distance between the coupling reference point and the coupling rotation pivot (meters).
`automaticCoupling` If `true`, coupling happens automatically when approaching another vehicle.
`skeletalMesh` Name of the Skeletal Mesh Component inside the Blueprint that contains the coupling mesh (e.g. `Exterior`).
`couplingBoneName` Name of the coupling rotation bone inside the skeleton (driven by animation).

The rear coupling works the same way:

couplingRear = {
    rotationOrigin     = "Coupling_B",
    couplingOffset     = 0.985,
    automaticCoupling  = true,
    skeletalMesh       = "Exterior",
    couplingBoneName   = "Coupling_Rotation2",
},

Cameras

Defines exterior cameras if the vehicle supports them. For AI vehicles, this is typically empty.

cameras = {
    exteriorCameras = {},
},

Braking Systems

Defines available brake systems and their maximum forces.

brakingSystems = {
    pneumatic5bar = {
        maxBrakeForce = 60,
    },
    electric = {
        maxBrakeForce = 50,
        maxBrakePower = 480,
    },
},
Entry Explanation
`pneumatic5bar.maxBrakeForce` Maximum brake force of the pneumatic brake (kN).
`electric.maxBrakeForce` Maximum brake force of the electric brake (kN).
`electric.maxBrakePower` Maximum braking power of the electric brake (kW).

Components

This list defines which Lua components are attached to the vehicle.

components = {
    LightManager,
    VehicleNumber,
    AudioManager,
    Berlin_PIS,
},
Component Purpose
`LightManager` Controls vehicle lighting logic.
`VehicleNumber` Handles vehicle number generation and decals.
`AudioManager` Manages audio playback and audio components.
`Berlin_PIS` Controls destination displays and announcements.

Audio (AI Bogie Audio)

Defines which Blueprint Audio Component is used for AI bogie sound playback.

audio = {
    audioBogieAI = {
        {
            audioComponent = "AiAudio",
        },
    },
},
Entry Explanation
`audioComponent = “AiAudio”` Name of the Audio Component inside the Vehicle Blueprint that plays the AI MetaSound / audio setup.

Lights

This section defines headlights and taillights, including:

  • which direction they apply to,
  • which mesh + material slot is affected,
  • which emissive parameters are set,
  • and which Light Components are controlled.
Concept Explanation
`direction = 1` Applies when the vehicle faces the forward direction.
`direction = -1` Applies when the vehicle faces the reverse direction.
`mesh` Skeletal Mesh Component name used for material manipulation (e.g. `Exterior`).
`materialSlot` The material slot name that contains emissive parameters.
`materialParams` Material parameter values applied when the light is active (usually emissive strength).
`lightComponents` Actual Unreal Light Components to switch on/off and configure (intensity, cone, radius, etc.).

Headlights example:

headLights = {
    {
        direction = 1,
        headlightElements = {
            {
                mesh = "Exterior",
                materialSlot = "GI1E_LightsExterior_mat",
                materialParams = {
                    ["Emissive01"] = 100,
                },
                lightComponents = {
                    {lightComponent ="Headlight1", intensity = 50, temperature = 4500, attenuationRadius = 500, innerConeAngle = 0, outerConeAngle = 70},
                    {lightComponent ="Headlight2", intensity = 50, temperature = 4500, attenuationRadius = 500, innerConeAngle = 0, outerConeAngle = 70},
                },
            },
        },
    },
},

Taillights example:

tailLights = {
    {
        mesh = "Exterior",
        materialSlot = "GI1E_LightsExterior_mat",
        direction = -1,
        materialParams = {
            ["Emissive02"] = 100,
        },
    },
},

PIS (Destination Displays & Announcements)

The PIS section defines:

  • which destination display components exist,
  • which announcement audio files are used,
  • the audio component for playback,
  • and additional announcement logic settings.

Key elements:

  • `destinationDisplays` defines display components (e.g. `ZZA`)
  • audio lists define announcement file assets
  • `audioComponent` defines the Blueprint Audio Component used for announcements

(Your provided PIS block remains valid and can be explained further in the next section.)


Vehicle Numbers

Defines how vehicle numbers are generated and displayed.

vehicleNumber = {
    labels = {
        {
            mesh = "Exterior",
            materialSlot = "DecalDigits_mat",
        },
    },
    poolName     = "Berlin_GI1E",
    poolValueMin = 1070,
    poolValueMax = 1094,
},
Entry Explanation
`labels.mesh` Mesh that receives the number decal material.
`labels.materialSlot` Material slot where number decals are applied.
`poolName` Name of the number pool.
`poolValueMin / poolValueMax` Range of numbers the vehicle can randomly receive.

(Continuation follows: copying variants with `deepCopy`, defining TrainCompositions, and registering content via `g_contentManager:addContent()`.)


© 2025 Simuverse Interactive · SubwaySim 2 Modding Wiki

All trademarks and registered trademarks are the property of their respective owners. This Wiki is provided for documentation and modding purposes only.

2025/12/12 12:06 · dcs
manual/subwaysim/vehicle_development/vehicle_lua.1768287837.txt.gz · Last modified: by dcs

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki