The Train Controller (Railroad System) v3.4 utilizes a decoupled, component-based framework designed around kinematic track evaluation and event-driven signals. Rather than relying entirely on standard Unity wheel physics—which often introduce jitter and derailment artifacts at high speeds—the core movement model relies on analytic mathematical curves calculated along continuous spline paths, synchronized with a deterministic physics update loop.
The system’s runtime logic is anchored by several interconnected manager and controller scripts:
RailNetworkManager: Acts as the central registry for track paths, switch points, and signal networks across the scene. It maintains a cached spatial hash of active rail segments to prevent costly linear searches during pathfinding.TrainController: Serves as the primary driver component for the locomotive. It coordinates engine state, throttle curves, dynamic braking, gear ratios, and front-bogie alignment.TrainCarriage: Attached to trailing train cars, handling distance-constrained relative placement, bogie articulation, dynamic coupling forces, and weight distribution.RailSignalController: Handles block signaling, switch-track state machines, and speed zone triggers via interface-driven observer patterns.To eliminate per-frame Garbage Collection (GC) allocations, the spline tracking algorithm avoids dynamic list instantiation and heap allocations during frame evaluation. Positions and tangents along the rail path are derived using pre-allocated native arrays or value-type structs passed by reference. Below is an example implementation demonstrating the non-allocating rail update routine used within the movement engine:
using UnityEngine;
using UnityEngine.Events;
namespace DynamicRailSystem
{
[RequireComponent(typeof(Rigidbody))]
public class RailFollower : MonoBehaviour
{
[SerializeField] private TrackSegmentSO _activeTrackData;
[SerializeField] private float _targetVelocity = 20f;
[SerializeField] private float _acceleration = 3.5f;
[Header("Events")]
public UnityEvent OnVelocityUpdated;
public UnityEvent OnSignalPassed;
private float _currentDistance;
private float _currentVelocity;
private Rigidbody _rb;
private void Awake()
{
_rb = GetComponent();
_rb.isKinematic = true;
_rb.interpolation = RigidbodyInterpolation.Interpolate;
}
private void FixedUpdate()
{
if (_activeTrackData == null) return;
// Accelerate smoothly toward target velocity using delta time
_currentVelocity = Mathf.MoveTowards(_currentVelocity, _targetVelocity, _acceleration * Time.fixedDeltaTime);
_currentDistance += _currentVelocity * Time.fixedDeltaTime;
// Non-allocating spline evaluation using struct references
_activeTrackData.EvaluatePointAndRotation(_currentDistance, out Vector3 targetPos, out Quaternion targetRot);
_rb.MovePosition(targetPos);
_rb.MoveRotation(targetRot);
OnVelocityUpdated?.Invoke(_currentVelocity);
}
public void SetTargetVelocity(float velocity)
{
_targetVelocity = velocity;
}
}
}
The editor environment for Train Controller (Railroad System) v3.4 relies heavily on custom property drawers, visual Handles API scene viewers, and ScriptableObject data containers. This isolates engine parameters and rail layouts from visual assets, allowing technical artists and designers to iterate without risking scene corruption.
Vehicle physics and line profiles are configured via distinct ScriptableObjects:
LocomotiveProfileSO: Defines torque curves, max brake pressure, mass distribution, pneumatic build-up delays, and derailment speed thresholds.TrackSegmentSO: Stores continuous bezier knot data, gradient angles, local speed limits, and signal block assignments.AudioVisualProfileSO: Maps velocity ranges to particle emission rates (e.g., steam or diesel exhaust) and controls pitch-shifting parameters for wheel-rail friction sound effects.The visual editor features inline custom inspectors that automatically render contextual controls inside the Scene View. Switch points can be toggled via clickable GUI buttons directly in the editor window. Custom Property Drawers provide visual curve previews for brake responsive curves and torque drop-offs directly within the Inspector panel, eliminating context switching between script settings and external editors.
Operating complex railroad systems with high car counts presents unique performance challenges regarding physics calculations, draw calls, and script execution overhead. The system uses specific architecture design choices to keep execution limits within tight mobile and VR performance budgets.
Traditional rigidbodies controlled via forces often fail at track switches or high speeds due to variable solver iterations. This architecture resolves movement analytically while maintaining dynamic physics interaction using Kinematic Rigidbodies:
FixedUpdate using Rigidbody.MovePosition, ensuring continuous collision detection (CCD) remains functional for objects hit by the train without running wheel-collider physics calculations.UnityEvent<float> triggers, executing only when velocity or signals change rather than polling data every frame inside an Update loop.Implementing the system into a clean scene requires establishing a track layout before instantiating train prefabs. Follow these steps to establish a functional prototype loop.
Create an empty GameObject in your hierarchy and attach the RailNetworkManager component. Use the editor menu (Tools > Railroad System > Create Track) to instantiate your first track node. Extend the track by holding the designated editor hotkey and clicking in the Scene View to place continuous spline knots. The editor automatically generates MeshCollider components along the rail path for wheel interaction audio and particle alignment.
Drag a train engine 3D model into the scene. Attach the TrainController script along with a standard Rigidbody component. Assign a valid LocomotiveProfileSO configuration file to the controller's profile slot. In the hierarchy, attach two child GameObjects representing the front and rear bogies, and link these references to the FrontBogieAnchor and RearBogieAnchor fields inside the Inspector.
Place trailing carriage prefabs behind the locomotive. Add the TrainCarriage component to each car. Using the custom Inspector utility, click Auto-Detect Couplers to align front and rear coupler joints. Finally, add the dynamic UI prefab into your Canvas and link the OnVelocityUpdated listener from the primary TrainController component to update the speed meter readout automatically at runtime.
| Category | Templates / Systems |
|---|---|
| Latest Version | v3.4.1 (2 tracked releases) |
| File Size | 348.69 MB |
| Added to Platform | February 5, 2026 |
| Views | 5 views |
| Downloads | 0 downloads |
| Favourites | 0 favourites |
| Official Store | Buy Original License on Unity Asset Store → |
| Issue with Package? | Report Broken Link → |