New in 0.1.2: - Debug color overlay: tint cars by physics state (yellow=frozen, cyan=fast-path, magenta=full-accuracy), individual toggles per state - Exclude locomotives from Physics Optimizer and Auto Freeze - Debug stats line in overlay showing live counts per state - Resync quality 1/16 option added Defaults tuned for new installs: - Resync quality: 1/4 -> 1/8 - Speed threshold: ~0.7 mph -> 0.2 mph - Overlay opacity: 100% -> 75% Rename: Physics Overhaul -> Physics Optimizer throughout |
||
|---|---|---|
| .gitignore | ||
| CarDebugVisualizer.cs | ||
| ConsistFreezer.cs | ||
| ConsistLOD.cs | ||
| ConsoleCommands.cs | ||
| Info.json | ||
| Main.cs | ||
| PhysicsOverhaulMod.csproj | ||
| PhysicsOverlayGUI.cs | ||
| PhysicsTimer.cs | ||
| README.md | ||
| Settings.cs | ||
Railroader Physics Optimizer
A Unity Mod Manager mod for Railroader that reduces CPU time spent on train physics without sacrificing gameplay.
This mod is HEAVILY experimental. Although it should be fully compatible and shouldnt corrupt your save, any use on your existing saves is your own risk and I accept no liability.
Features
Physics Optimizer (LOD fast-path)
Cars farther than a configurable distance threshold (default 30 m) get a lightweight position update instead of running the full Bezier-curve solver every physics tick. Every few ticks the car resyncs against the full solver to stay numerically correct. The result: far fewer expensive curve evaluations per frame, with limited to no visible difference to gameplay.
Auto Freeze
Consists that are both slow (< 0.3 m/s) and far from the camera (> 200 m) are skipped entirely by the Verlet integration step. If running the wonderful Stock Optimizer mod please disable this feature and beware that there might be instability.
In-Game Profiler Overlay
A movable HUD window shows a stacked line chart of frame time over the last 300 physics ticks (~5 seconds). Layers from the bottom up:
| Color | Layer |
|---|---|
| Blue | Render frame time (GPU + CPU render work) |
| Green | FixedUpdate total (all physics) |
| Yellow | Tick() only (Verlet integration) |
| Orange | PositionCars (3D position update) |
Reference lines at 16.7 ms (60 fps) and 33.3 ms (30 fps) are always on screen regardless of how well the game is running. Toggle the overlay with /rpf overlay or from the UMM settings panel.
Theory of Operation
Why physics is expensive in Railroader
Each physics tick (FixedUpdate), TrainController calls PositionWheelBoundsFront for every car. This method walks the spline to find the 3D position and orientation for each truck — two expensive distance-to-parameter lookups per car. With long consists on curved track, this dominates frame time.
Physics Optimizer detail
The mod patches Car.PositionWheelBoundsFront with a Harmony prefix. When a car is far from the camera and all its couplers are coupled:
- Track bounds (
WheelBoundsF/R) are still updated every tick — the constraint solver needs them. - Truck positions are computed, but only every N ticks (controlled by
ResyncInterval). Between resyncs, the car keeps the body rotation from the previous tick. PositionAccuracymatches what the full path would use (Highwhen visible,Standardotherwise) so there is no positional jump when the camera enters the threshold.OnPositionis fired soTrainController.CarDidPositionruns — this keeps the car-culler bounding sphere, spatial hash, and segment cache current.LocationF/LocationRare updated each tick so the segment cache never goes stale.
Auto Freeze detail
ShouldSkipTick is replaced. This mod tracks each car individually and skips cars that are far away and very slow, reducing wasteful simulation of parked cars.
Sampling model (the "% of FixedUpdate" number)
The profiler measures time with Stopwatch.GetTimestamp() (nanosecond resolution, no GC pressure). It accumulates over 60-tick windows. "% of FixedUpdate" is how much of the total physics budget Tick() alone consumed that window — a high percentage means Verlet integration dominates; a low percentage means air brakes, coupler forces, or position updates are the bottleneck.
Installation
Requirements
- Unity Mod Manager installed and configured for Railroader
- Railroader (Steam)
Installing with Unity Mod Manager (recommended)
- Download the latest release zip.
- Open Unity Mod Manager (Ctrl+F10 in game, or the standalone installer).
- Drag the zip onto the Mods tab, or click Install Mod and select the zip.
- Launch the game.
Manual installation
- Unzip the release into
<Railroader install folder>\Mods\RailroaderPhysicsOverhaul\. - The folder must contain
Info.jsonandRailroaderPhysicsOverhaul.dll. - Launch the game.
Console Commands
Open the in-game console and type /rpf <subcommand>:
| Command | Description |
|---|---|
/rpf help |
List all subcommands |
/rpf overlay |
Toggle the profiler HUD |
/rpf timing |
Print the current timing report to the console |
/rpf dump |
Dump the selected consist's state (cars, speed, coupling, segment) |
/rpf lod <meters> |
Set the LOD distance threshold |
/rpf lod off |
Disable the LOD fast-path entirely |
/rpf freeze |
Freeze the selected consist's physics |
/rpf unfreeze |
Unfreeze the selected consist |
/rpf forceactive |
Toggle ForceActive (bypasses the at-rest check for profiling) |
Settings
Open UMM (Ctrl+F10), select Physics Optimizer. All settings auto-save on change.
| Setting | Default | Description |
|---|---|---|
| Physics Optimizer | On | Enable/disable the LOD fast-path |
| Distance Threshold | 30 m | Cars beyond this distance use the fast path |
| Resync Interval | 4 ticks | Full recalculation every N ticks (1 = every tick, no dead-reckoning) |
| Auto Freeze | On | Enable/disable the individual-consist freeze |
| Auto Freeze Distance | 200 m | Consists beyond this distance are eligible for freezing |
| Auto Freeze Speed | 0.3 m/s | Maximum speed for a consist to be considered stopped |
| Show Overlay | On | Show/hide the profiler HUD on game load |
| Overlay Opacity | 100% | Profiler window background opacity |
| Blacklist/Whitelist | Off | Filter specific road numbers in or out of LOD treatment |
Building from Source
dotnet build PhysicsOverhaulMod.csproj
The build output goes directly to <Railroader install folder>\Mods\RailroaderPhysicsOverhaul\. The project references game DLLs relative to the source folder, so it must be placed inside the Railroader game directory.
Prerequisites: .NET SDK 6 or later, Railroader installed in the same directory tree.