Class EngineComponent
Simulates internal combustion engines (ICE) or electric motors. Supplies drivetrain power based on throttle input, RPM, and power curves.
Inherited Members
Namespace: NWH.VehiclePhysics2.Powertrain
Assembly: NWH.VehiclePhysics2.dll
Syntax
[Serializable]
public class EngineComponent : PowertrainComponent
Remarks
Output power is powerCurve sampled at normalized RPM, times maxPower, times the product of every powerModifiers callback. ICE needs ignition and a starter, stalls below stallRPM and holds idleRPM through the idle governor; Electric has no starter, cannot stall and runs in both directions.
Fields
MIN_REV_LIMITER_RPM
Minimum allowed rev limiter RPM to prevent division by zero in physics calculations.
Declaration
public const float MIN_REV_LIMITER_RPM = 100
Field Value
| Type | Description |
|---|---|
| float |
RPM_TO_ANGULAR_VELOCITY
Conversion factor from RPM to angular velocity in rad/s (2π/60).
Declaration
public const float RPM_TO_ANGULAR_VELOCITY = 0.10471976
Field Value
| Type | Description |
|---|---|
| float |
WATTS_TO_KILOWATTS
Conversion factor from watts to kilowatts (1/1000).
Declaration
public const float WATTS_TO_KILOWATTS = 0.001
Field Value
| Type | Description |
|---|---|
| float |
autoStartOnThrottle
Enables automatic engine starting when throttle input is detected. Only applies to ICE engines - electric motors don't require starting.
Declaration
[Tooltip("If true, the starter runs for [starterRunTime] seconds if the engine receives any throttle input.")]
public bool autoStartOnThrottle
Field Value
| Type | Description |
|---|---|
| bool |
Remarks
Throttle on a stopped ICE engine engages the starter for startDuration, so no separate ignition input is needed. Turn it off for manual ignition or race start procedures.
calculateTorqueDelegate
Custom delegate for calculating engine torque output.
Declaration
[Tooltip("Assign your own delegate to use a different type of torque calculation.")]
public EngineComponent.CalculateTorque calculateTorqueDelegate
Field Value
| Type | Description |
|---|---|
| EngineComponent.CalculateTorque |
Remarks
Defaults to CalculateTorqueICE or CalculateTorqueElectric depending on engineType. Assign to replace the torque model outright.
damageLossIncrease
Additional engine loss percentage added at full damage. Increases engine braking and parasitic losses.
Declaration
[Range(0, 0.5)]
[Tooltip("Additional engine loss percentage at full damage. Increases engine braking.")]
public float damageLossIncrease
Field Value
| Type | Description |
|---|---|
| float |
damagePowerReduction
Maximum power reduction at full damage (0-1). 0.8 means 80% power loss when damage=1.
Declaration
[Range(0, 1)]
[Tooltip("Maximum power reduction at full damage (0-1). 0.8 = 80% power loss at damage=1.")]
public float damagePowerReduction
Field Value
| Type | Description |
|---|---|
| float |
engineBrakingRpmRise
How strongly off-throttle engine-braking torque rises with RPM (0-1). At 0, drag torque is roughly constant across the rev range (original behaviour). At 1, drag torque grows linearly with RPM, approximating real engine friction/pumping (FMEP) which increases with engine speed.
Declaration
[Range(0, 1)]
[Tooltip("How strongly off-throttle engine braking rises with RPM. 0 = constant drag torque across the rev range (original behaviour, presets unchanged). 1 = drag torque grows linearly with RPM, matching the rising friction/pumping of a real engine, so engine braking is stronger near the redline.")]
public float engineBrakingRpmRise
Field Value
| Type | Description |
|---|---|
| float |
engineLossPercent
Engine parasitic losses as a percentage of maximum power, ranging from 0 (no losses) to 1 (100% loss).
Declaration
[Range(0, 1)]
[Tooltip("Loss power (pumping, friction losses) is calculated as the percentage of maxPower.\r\nShould be between 0 and 1 (100%).")]
public float engineLossPercent
Field Value
| Type | Description |
|---|---|
| float |
Remarks
Covers friction, pumping and accessory drag. Higher values give stronger engine braking and a slower coast-down.
engineType
Engine type. ICE (Internal Combustion Engine) supports features such as starter, stalling, etc. Electric engine (motor) can run in reverse, cannot be stalled and does not use starter.
Declaration
[Tooltip("Engine type. ICE (Internal Combustion Engine) supports features such as starter, stalling, etc.\r\nElectric engine (motor) can run in reverse, can not be stalled and does not use starter.")]
[ShowInTelemetry(NaN, NaN, null, null, 1)]
public EngineComponent.EngineType engineType
Field Value
| Type | Description |
|---|---|
| EngineComponent.EngineType |
exhaustPosition
Position of the exhaust in local space relative to the vehicle transform.
Declaration
[Tooltip("Position of the exhaust relative to the vehicle. Turn on gizmos to see the marker.")]
public Vector3 exhaustPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
Remarks
Drives exhaust particles and sound positioning. Shown as a gizmo when gizmos are on.
flyingStartEnabled
If true, the engine will be started immediately, without running the starter, when the vehicle is enabled. Sets engine angular velocity to idle angular velocity.
Declaration
[Tooltip("If true the engine will be started immediately, without running the starter, when the vehicle is enabled.\r\nSets engine angular velocity to idle angular velocity.")]
public bool flyingStartEnabled
Field Value
| Type | Description |
|---|---|
| bool |
forcedInduction
Turbocharger or supercharger.
Declaration
[Tooltip("Turbocharger or supercharger.")]
public EngineComponent.ForcedInduction forcedInduction
Field Value
| Type | Description |
|---|---|
| EngineComponent.ForcedInduction |
generatedPower
Power generated by the engine in kW
Declaration
[ShowInTelemetry(0, 500, "0.0", "kW", 1)]
[NonSerialized]
[Tooltip("Power generated by the engine in kW")]
public float generatedPower
Field Value
| Type | Description |
|---|---|
| float |
idleRPM
Target idle RPM that the idle control system maintains when the engine is running with no throttle input.
Declaration
[SerializeField]
[Tooltip("RPM at which idler circuit will try to keep RPMs when there is no input.")]
public float idleRPM
Field Value
| Type | Description |
|---|---|
| float |
Remarks
The idle governor trims throttle to hold this RPM. ICE only; electric motors can sit at 0 RPM. Keep it well above stallRPM or the engine stalls during normal idle.
ignition
Ignition switch state. When false, the engine cannot generate power even if running.
Declaration
public bool ignition
Field Value
| Type | Description |
|---|---|
| bool |
Remarks
Prefer StartEngine() and StopEngine() over writing this field, they also fire the events and reset the starter state.
isRunning
Is the engine currently running? Requires ignition to be enabled and engine RPM above the stall RPM.
Declaration
[NonSerialized]
[ShowInTelemetry(NaN, NaN, null, null, 1)]
public bool isRunning
Field Value
| Type | Description |
|---|---|
| bool |
load
Current load of the engine, based on the power produced.
Declaration
[NonSerialized]
[ShowInTelemetry(0, 1, "0.00", null, 1)]
public float load
Field Value
| Type | Description |
|---|---|
| float |
maxPower
Peak engine power in kilowatts (kW), produced at optimal RPM.
Declaration
[ShowInSettings("Max. Power", 20, 400, 10)]
[Tooltip("Maximum engine power in [kW].")]
public float maxPower
Field Value
| Type | Description |
|---|---|
| float |
Remarks
Multiplied by the powerCurve coefficient to get instantaneous power at a given RPM.
onRevLimiter
Called when engine hits rev limiter.
Declaration
[Tooltip("Called when engine hits rev limiter.")]
public UnityEvent onRevLimiter
Field Value
| Type | Description |
|---|---|
| UnityEvent |
onStart
Called when engine is started.
Declaration
[Tooltip("Called when engine is started.")]
public UnityEvent onStart
Field Value
| Type | Description |
|---|---|
| UnityEvent |
onStop
Called when engine is stopped.
Declaration
[Tooltip("Called when engine is stopped.")]
public UnityEvent onStop
Field Value
| Type | Description |
|---|---|
| UnityEvent |
powerCurve
Power curve with RPM range [0,1] on the X axis and power coefficient [0,1] on Y axis. Both values are represented as percentages and should be in the 0 to 1 range. Power coefficient is multiplied by maxPower to get the final power at a given RPM.
Declaration
[Tooltip("Power curve with RPM range [0,1] on the X axis and power coefficient [0,1] on Y axis.\r\nBoth values are represented as percentages and should be in 0 to 1 range.\r\nPower coefficient is multiplied by maxPower to get the final power at given RPM.")]
public AnimationCurve powerCurve
Field Value
| Type | Description |
|---|---|
| AnimationCurve |
powerModifiers
List of callbacks that influence engine power. Examples would be traction control that reduces power (returns less than 1) or forced induction which increases power (returns more than 1). Can also be used by modules to reduce engine power in certain situations. The final power modifier value is calculated by multiplying return values of all callbacks.
Declaration
[Tooltip("List of callbacks that influence engine power. Examples would be traction control which\r\nreduces power (returns less than 1) or forced induction which increases power (returns more than 1).\r\nCan also be used by modules to reduce engine power in certain situations.\r\nFinal power modifier value is calculated by multiplying return values of all callbacks.")]
[NonSerialized]
public List<EngineComponent.PowerModifier> powerModifiers
Field Value
| Type | Description |
|---|---|
| List<EngineComponent.PowerModifier> |
revLimiterActive
Is the engine currently hitting the rev limiter?
Declaration
[NonSerialized]
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[Tooltip("Is the engine currently hitting the rev limiter?")]
public bool revLimiterActive
Field Value
| Type | Description |
|---|---|
| bool |
revLimiterCutoffDuration
If engine RPM rises above revLimiterRPM, how long should fuel cutoff last? Higher values make hitting rev limiter more rough and choppy.
Declaration
[Tooltip("If engine RPM rises above revLimiterRPM, how long should fuel cutoff last?\r\nHigher values make hitting rev limiter more rough and choppy.")]
public float revLimiterCutoffDuration
Field Value
| Type | Description |
|---|---|
| float |
revLimiterRPM
Engine RPM at which rev limiter activates.
Declaration
[Tooltip("Engine RPM at which rev limiter activates.")]
public float revLimiterRPM
Field Value
| Type | Description |
|---|---|
| float |
rpmPercent
RPM as a percentage of maximum RPM.
Declaration
[NonSerialized]
public float rpmPercent
Field Value
| Type | Description |
|---|---|
| float |
runModifiers
List of callbacks that influence if the engine can run. All modifiers have to return true for the engine to run.
Declaration
[NonSerialized]
[Tooltip("List of callbacks that influence if the engine can run. All modifiers have to return true for the engine to run.")]
public List<EngineComponent.CanRunModifier> runModifiers
Field Value
| Type | Description |
|---|---|
| List<EngineComponent.CanRunModifier> |
stallRPM
Minimum RPM below which the ICE engine will stall and stop running. Set to 0 to disable stalling.
Declaration
[SerializeField]
[Tooltip("RPM at which the engine will stall. Set to 0 to disable stalling.")]
public float stallRPM
Field Value
| Type | Description |
|---|---|
| float |
Remarks
Electric motors ignore this and run at any RPM including zero. Keep it 400-600 RPM below idleRPM; too close and the engine stalls during normal idle or low-speed maneuvering.
startDuration
Duration in seconds that the starter motor operates when starting the engine.
Declaration
[Tooltip("Duration in seconds that the starter motor operates when starting the engine.")]
public float startDuration
Field Value
| Type | Description |
|---|---|
| float |
Remarks
Starter torque is sized from engine inertia and this duration, so too short a value fails to reach idle and stalls straight after starting. Floored at 0.1 s to bound the impulse.
starterActive
Is the starter currently active?
Declaration
[NonSerialized]
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[Tooltip("Is the starter currently active?")]
public bool starterActive
Field Value
| Type | Description |
|---|---|
| bool |
throttleLossFactorResponseRate
Rate (1/s) at which the throttle-position loss factor approaches its target. Higher = snappier engine-braking transition off-throttle.
Declaration
[Range(0.5, 50)]
[Tooltip("Rate (1/s) at which the throttle-position loss factor approaches its target. The pumping-loss curve jumps ~20x when throttle is fully released, which propagates through a locked diff to wheels as a sudden negative torque step that destabilises the free-rolling friction solver. Smoothing across frames keeps the engine-drag transition gradual. Default 8 = ~0.125s time constant (perceptually instant). Raise toward 20+ if engine braking feels soggy.")]
public float throttleLossFactorResponseRate
Field Value
| Type | Description |
|---|---|
| float |
throttlePosition
Engine throttle position. 0 for no throttle and 1 for full throttle.
Declaration
[NonSerialized]
[ShowInTelemetry(0, 1, "0.00", null, 1)]
public float throttlePosition
Field Value
| Type | Description |
|---|---|
| float |
Properties
EstimatedPeakPower
Peak power as calculated from the power curve. If the power curve peaks at Y=1, the peak power will equal max power field value. Call UpdatePeakPowerAndTorque() after changing power, the power curve, or the RPM range to update this value.
Declaration
public float EstimatedPeakPower { get; }
Property Value
| Type | Description |
|---|---|
| float |
EstimatedPeakPowerRPM
RPM at which the peak power is achieved. Call UpdatePeakPowerAndTorque() after changing power, the power curve, or the RPM range to update this value.
Declaration
public float EstimatedPeakPowerRPM { get; }
Property Value
| Type | Description |
|---|---|
| float |
EstimatedPeakTorque
Peak torque value as calculated from the power curve. Call UpdatePeakPowerAndTorque() after changing power, the power curve, or the RPM range to update this value.
Declaration
public float EstimatedPeakTorque { get; }
Property Value
| Type | Description |
|---|---|
| float |
EstimatedPeakTorqueRPM
RPM at which the engine achieves the peak torque, calculated from the power curve. Call UpdatePeakPowerAndTorque() after changing power, the power curve, or the RPM range to update this value.
Declaration
public float EstimatedPeakTorqueRPM { get; }
Property Value
| Type | Description |
|---|---|
| float |
IsRunning
Pre-14.0 name of isRunning.
Declaration
[Obsolete("Renamed to isRunning.")]
public bool IsRunning { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsStalled
Is the engine stalled or stalling? ICE engine only.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
public bool IsStalled { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Load
Pre-14.0 name of load.
Declaration
[Obsolete("Renamed to load.")]
public float Load { get; }
Property Value
| Type | Description |
|---|---|
| float |
RPMPercent
Pre-14.0 name of rpmPercent.
Declaration
[Obsolete("Renamed to rpmPercent.")]
public float RPMPercent { get; }
Property Value
| Type | Description |
|---|---|
| float |
ThrottlePosition
Pre-14.0 name of throttlePosition.
Declaration
[Obsolete("Renamed to throttlePosition.")]
public float ThrottlePosition { get; }
Property Value
| Type | Description |
|---|---|
| float |
Methods
CalculateTorqueElectric(float, float)
Calculates output torque for electric motor powerplants.
Declaration
public float CalculateTorqueElectric(float angularVelocity, float dt)
Parameters
| Type | Name | Description |
|---|---|---|
| float | angularVelocity | Current engine angular velocity in rad/s. |
| float | dt | Time step for the calculation in seconds. |
Returns
| Type | Description |
|---|---|
| float | Total torque output in N⋅m, including generated power and resistive losses. |
Remarks
Constant torque below the base speed, constant power above it. No starter and no idle system, and torque follows the shaft direction so the motor runs both ways. Throttle is zeroed while the transmission shifts to keep torque spikes out.
CalculateTorqueICE(float, float)
Calculates output torque for internal combustion engine (ICE) powerplants.
Declaration
public float CalculateTorqueICE(float angularVelocity, float dt)
Parameters
| Type | Name | Description |
|---|---|---|
| float | angularVelocity | Current engine angular velocity in rad/s. |
| float | dt | Time step for the calculation in seconds. |
Returns
| Type | Description |
|---|---|
| float | Total torque output in N⋅m, including generated power, losses, starter motor, and idle correction. |
Remarks
Implements ICE simulation: power curve torque, idle control, starter motor, rev limiter, stall logic, friction/pumping losses, and forced induction. Throttle is auto-managed during shifting and starting. Loss torque provides engine braking off-throttle.
GetPeakPower(out float, out float)
Calculates the peak power output and the RPM at which it occurs from the power curve.
Declaration
public void GetPeakPower(out float peakPower, out float peakPowerRpm)
Parameters
| Type | Name | Description |
|---|---|---|
| float | peakPower | Output parameter receiving the maximum power value in kW. |
| float | peakPowerRpm | Output parameter receiving the RPM at which peak power occurs. |
Remarks
Samples the curve in 5% steps for the highest coefficient, multiplies by maxPower and applies the forced induction multiplier. The sample X gives the RPM fraction.
GetPeakTorque(out float, out float)
Calculates the peak torque output and the RPM at which it occurs from the power curve.
Declaration
public void GetPeakTorque(out float peakTorque, out float peakTorqueRpm)
Parameters
| Type | Name | Description |
|---|---|---|
| float | peakTorque | Output parameter receiving the maximum torque value in N⋅m. |
| float | peakTorqueRpm | Output parameter receiving the RPM at which peak torque occurs. |
Remarks
Samples the curve in 5% steps between idleRPM and revLimiterRPM, converting each sample with T = P / w, then applies the forced induction multiplier.
GetWorldPosition(VehicleController)
Gets the world position of the engine component.
Declaration
public override Vector3 GetWorldPosition(VehicleController vc)
Parameters
| Type | Name | Description |
|---|---|---|
| VehicleController | vc | The vehicle controller. |
Returns
| Type | Description |
|---|---|
| Vector3 | Engine position in world space. |
Overrides
IntegrateDownwards(float, WheelControllerGroup)
Main physics update method that solves engine dynamics and propagates torque through the powertrain.
Declaration
public void IntegrateDownwards(float DeltaTime, WheelControllerGroup group = null)
Parameters
| Type | Name | Description |
|---|---|---|
| float | DeltaTime | Physics time step in seconds. |
| WheelControllerGroup | group | Optional wheel group receiving the downward powertrain integration. |
Remarks
Called each physics frame by Powertrain.VC_FixedUpdate(). Updates engine state, queries wheel velocities, calculates torque, propagates through drivetrain, and integrates RPM. Uses semi-implicit integration with generated, reaction, and return torques. Do not call manually.
StartEngine()
Starts the engine, engaging the starter motor if needed for ICE engines.
Declaration
public void StartEngine()
Remarks
ICE either jumps straight to idle RPM when flyingStartEnabled is set, or cranks for startDuration. Electric starts instantly. Refused at full damage or when any run modifier returns false. Fires onStart on the stopped to started edge only.
StartStopEngine()
Toggles the engine between running and stopped states.
Declaration
public void StartStopEngine()
Remarks
ICE goes through the starter unless flyingStartEnabled is set; electric starts instantly.
StopEngine()
Stops the engine and resets all engine operating parameters.
Declaration
public void StopEngine()
Remarks
Cuts ignition, cancels the starter and rev-limiter cutoff, and zeroes throttle, load and the idle governor state. RPM then decays on drivetrain inertia and losses. Fires onStop on the started to stopped edge only.
UpdatePeakPowerAndTorque()
Recalculates peak power and torque values from the current power curve and engine settings.
Declaration
public void UpdatePeakPowerAndTorque()
Remarks
Call after modifying power curve, max power, rev limiter, or forced induction. Automatically called during initialization; only needed for runtime changes.
VC_Disable(bool)
Disables the powertrain component and resets its operational values.
Declaration
public override bool VC_Disable(bool calledByParent)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | calledByParent | True if this method was called by a parent component, false if called directly. |
Returns
| Type | Description |
|---|---|
| bool | True if the component was successfully disabled, false otherwise. |
Overrides
Remarks
Zeroes angular velocity and torque so the next enable starts clean.
VC_Enable(bool)
Enables the component and starts its updates.
Declaration
public override bool VC_Enable(bool calledByParent)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | calledByParent | True when called by a parent ManagerVehicleComponent fan-out or the VehicleController enable/disable loop. The LOD system passes false. |
Returns
| Type | Description |
|---|---|
| bool | True if successfully enabled, false otherwise |
Overrides
Remarks
Initializes the component first if it is not initialized yet. A parent bulk enable is refused unless the last disable also came from a parent, so it cannot resurrect a component turned off by LOD, by a script, or disabled in StateSettings.
VC_Initialize()
Initializes the powertrain component and establishes connections with other components.
Declaration
protected override void VC_Initialize()
Overrides
Remarks
Floors inertia at MIN_INERTIA and resolves the input and output links from persisted names.
VC_SetDefaults()
Sets the component's properties to their default values.
Declaration
public override void VC_SetDefaults()
Overrides
Remarks
Sets inertia to 0.02 kg⋅m², suitable for most powertrain components.
VC_Validate(VehicleController)
Validates the powertrain component configuration and logs warnings for potential issues.
Declaration
public override void VC_Validate(VehicleController vc)
Parameters
| Type | Name | Description |
|---|---|---|
| VehicleController | vc | The vehicle controller that contains this component. |
Overrides
Remarks
Checks inertia minimum (0.0001) and output connections. Called during vehicle validation.