NWH Vehicle Physics 2
Search Results for

    Show / Hide Table of Contents

    FFB Input Provider (Steering Wheel Support)

    FFBInputProvider adds steering wheel support with force feedback (FFB) to NWH Vehicle Physics 2 using the DirectInput API. It works with any DirectInput-compatible device including Logitech, Thrustmaster, Fanatec, Moza, Simagic, Simucube, and other manufacturers.

    Warning: Requires two front wheels. Windows only - DirectInput does not exist on other platforms.

    The force sent to the wheel is derived from the tire model, not from a set of canned effects. Self-aligning torque comes from the same aligning moment the tires produce in the physics step, so the wheel lightens as the front tires approach the grip limit and weights up again as they recover.

    Compatible Devices

    All DirectInput-compatible devices work, including:

    Device Status
    Simucube 2 Pro/Ultimate Verified
    Fanatec DD1/DD2/CSL DD Verified
    Moza R9 Verified
    Simagic Alpha Verified
    Logitech G29/G920/G923/PRO Verified
    Thrustmaster TX/T300 Verified

    Setup

    1. Install Unity-DirectInput Package

    Add the Unity-DirectInput package via Unity Package Manager:

    1. Open Window > Package Manager
    2. Click the + button and select Add package from git URL
    3. Enter: https://github.com/imDanoush/Unity-DirectInput.git
    4. Click Install
    5. Restart Unity after installation

    2. Import the DirectInput FFB Sample

    1. Open Window > Package Manager
    2. Find NWH Vehicle Physics 2 in the list
    3. Expand Samples
    4. Import DirectInput FFB Sample

    3. Add FFBInputProvider and DIInputManager to Scene

    1. Add the FFBInputProvider prefab from the sample to your scene, OR
    2. Add both DIInputManager and FFBInputProvider components to a GameObject

    The input provider requires DIInputManager to function and will automatically detect the first FFB-capable device.

    Note: only one DIInputManager may exist in the scene. Both the FFBInputProvider prefab and the DirectInputManager prefab carry one, so adding both gives you two managers fighting over the device. Use one or the other.

    4. Configure Input Mappings

    Configure your device's axis and button mappings via the DIInputManager component. The axis and button names on FFBInputProvider are string keys that must match the mapping names configured there - a typo produces a silently dead axis, not an error.

    Default Axis Mappings:

    • Steering: X axis
    • Throttle: Y axis
    • Brake: Z rotation
    • Clutch: Z axis

    Default Button Mappings:

    • Shift Up/Down: Paddles or sequential shifter
    • H-Pattern: Buttons for each gear position

    5. Set Wheelbase Torque and Check Polarity

    Set wheelbaseTorque to your device's actual peak torque before anything else - every force in the system is scaled against it.

    Then check the direction of the force. Output polarity is not the same on every device: DirectInput does not define which sign means "push left", so roughly half of all wheels need the output inverted. Drive slowly and turn:

    • Correct: the wheel resists the turn and tries to return to centre.
    • Wrong: the wheel pulls itself further into the turn and runs to full lock.

    If it is wrong, enable invertFFBOutput. Do not try to correct it with negative coefficients elsewhere - that inverts the detail effects along with the main force.

    Gotcha: invertFFBOutput, softLockStrength, softLockRampDeg and collisionFullScaleDeltaV exist on the component but are not drawn by the custom inspector. To reach them, switch the Inspector to Debug mode (context menu at the top right of the Inspector window), or set them from a script.

    FFBInputProvider Settings

    The sections below match the inspector layout.

    Core Settings

    Setting Description
    vehicleController Vehicle to read forces from. Follows the active vehicle if a VehicleChanger is present.
    useDirectInput Bypasses the steering smoothing and speed-sensitivity in Steering, giving 1:1 wheel-to-road angle. Leave on for a wheel.
    hShifterUse34asDR Uses H-pattern positions 3 and 4 as Drive and Reverse, for an automatic gearbox driven with a shifter.

    Hardware Configuration

    Setting Description
    wheelbaseTorque Peak torque of your wheel in Nm. G29/G923 = 2-3, T300 = 4-5, CSL DD = 5-8, Moza R9 = 9, DD1/DD2 = 15-20, Simucube 2 Pro = 25. Set this correctly first - it is the reference every other force is scaled against.
    deviceRotationRange Physical rotation range the wheel is configured for in its driver, in degrees (typically 900). Must match the driver setting or the steering angle will not line up.
    steeringSensitivity Multiplier on steering input. Leave at 1 for a 1:1 wheel.

    Steering Geometry

    These two set how much of the steering weight comes from vertical load rather than from lateral force. Load-based weight survives a slide and lightens over a crest, which is what makes the wheel feel connected to the road rather than only to the tires.

    Setting Description
    casterAngle Caster in degrees. 3-7 for road cars, 5-8 for rally. Overridden per vehicle by FFBVehicleSettings.casterAngle when that is above 0.
    kingpinOffset Lateral distance from the kingpin axis to the contact patch, in metres. Drives parking effort and the lightening felt over a crest.

    Force Feedback Settings

    Setting Description
    overallEffectStrength Master multiplier. 0 disables force feedback.
    forceFeedbackEffect Curve scaling FFB strength against steering angle.
    springEffect Curve scaling the DirectInput spring effect against steering angle.
    springEffectStrength DirectInput spring (centring) effect. 0 by default - centring already comes from the tire model.
    lowSpeedFriction Steering resistance while stationary or nearly so.
    friction Steering resistance at speed.
    centeringForceStrength Legacy suspension-based centring.
    centeringForceOffset Offsets the centre by the drift angle, so the wheel centres on the direction of travel rather than straight ahead.
    collisionEffectMultiplier Strength of the impact jolt.

    High-Rate Output and Mixing

    Force is sent to the device from a dedicated thread rather than once per rendered frame, so kerb and grip-limit detail is not tied to your framerate.

    Setting Description
    ffbThreadHz Output rate of the FFB thread. The default 333 Hz covers the 40-150 Hz band where kerb, rut and grip-limit detail live. Lower it only if you are chasing CPU.
    textureBudget Ceiling on the combined road-texture effects as a fraction of full force, before mixing with the self-aligning torque. Keeps detail from drowning out the main force.
    softClipKnee Force is linear up to this fraction of full scale, then compresses smoothly instead of clipping flat. 1 = hard clip.
    maxSlewNmPerSec Limit on how fast output torque may change, in Nm/s. Bounds impact spikes a real steering rack could not produce. 0 = unlimited.

    Damping and Centering

    Setting Description
    damperStrength Velocity damper strength. Stabilises the wheel without attenuating the tire signal.
    damperFadeSpeed Vehicle speed (m/s) at which the damper drops to its high-speed floor.
    damperHighSpeedFloor Damper multiplier at and above the fade speed. This is the steering "drag" felt at speed - too low and a direct-drive wheel feels like it is freewheeling, too high and road detail smears.
    frictionCoeffAmount Small constant DirectInput friction so the wheel never feels loose. Fades as the tires start to slide.
    suspensionCenteringStrength Legacy suspension-difference centring offset. 0 by default; useful only on low-torque belt or gear wheels.

    Texture Effects

    Setting Description
    roadTextureStrength Strength of road texture. Derived by high-pass filtering the real rack force, so it is automatically correct for surface and speed. 0 = off.

    Note: earlier versions had separate kerb, scrub, engine-resonance and ABS oscillators. Those were fixed-frequency tones advanced once per frame, which aliases - a 55 Hz kerb tone folds down to about 5 Hz at 60 fps, and its pitch changes with framerate. They are replaced by this single term.

    Suspension Feedback

    Setting Description
    suspensionBumpStrength Kerb, pothole and road-surface feel through the steering.
    suspensionBumpThreshold Minimum suspension velocity (m/s) before bump feedback triggers. Lower is more sensitive.

    Input Inversion, Axes and Deadzones

    flipSteeringInput, flipThrottleInput, flipBrakeInput, flipClutchInput and flipHandbrakeInput invert a pedal or axis that reads backwards. The pedal flips default to on, which suits most wheels - a pedal that reads full when released usually needs its flip turned off, not on.

    steeringAxis0to1 tells the provider whether the steering axis reports 0-1 (most devices) or already reports -1 to 1.

    Deadzones (throttleDeadzone, brakeDeadzone, clutchDeadzone, handbrakeDeadzone, steeringDeadzone) trim noise around the resting position of worn pedals. Steering deadzone defaults to 0 and should normally stay there.

    Axis names (steeringAxis, throttleAxis, brakeAxis, clutchAxis, handbrakeAxis) and the shifter button names must match the mappings in DIInputManager.

    Fields Not Shown in the Inspector

    Setting Description
    invertFFBOutput Flips the sign of the force sent to the device. See step 5 of Setup.
    softLockStrength Strength of the end stop felt past full steering lock, as a fraction of full device torque. 0 disables it.
    softLockRampDeg Degrees of wheel travel past lock over which the end stop ramps up to full strength.
    collisionFullScaleDeltaV Impact speed change (m/s) that produces a full-scale collision jolt.

    Per-Vehicle Tuning

    Add FFBVehicleSettings to your VehicleController GameObject to scale FFB per vehicle. A truck and a formula car want different steering weight from the same physical wheel.

    Setting Description
    overallCoeff Overall FFB strength for this vehicle.
    satCoefficient Self-aligning torque multiplier.
    mechanicalTrailCoeff Multiplier on the caster/kingpin load term. 0 = tire trail only (very light), 0.2 = baseline, above 1 = exaggerated weight.
    centeringCoeff Centring force multiplier.
    casterAngle Caster for this vehicle. 0 = use the provider's global value.
    kingpinOffset Kingpin offset for this vehicle, in metres. Negative = use global.
    wheelRotationRange Steering wheel rotation range for this vehicle, in degrees.
    staticFrontLoadOverride Measured static front axle load in Newtons, used to normalise how load modulates the rack force. 0 = estimate as half the vehicle weight.
    frictionCoeff At-speed friction multiplier.
    lowSpeedFrictionCoeff Stationary friction multiplier.
    longitudinalCoeff How much braking and acceleration are felt through the steering.
    scrubRadius Scrub radius in metres. Typical 0.01-0.03 for road cars.
    suspensionBumpStrength Bump feedback for this vehicle. Negative = use global.
    suspensionBumpThreshold Bump sensitivity for this vehicle. Negative = use global.

    Gotcha: fields whose "inherit" value is negative (kingpinOffset, suspensionBumpStrength, suspensionBumpThreshold) treat 0 as a real value meaning off. Leave them negative unless you actually want that effect disabled on this vehicle.

    Gotcha: wheelRotationRange here also sets the steering ratio used to convert rack torque to torque at the rim. It is not the same field as Steering.steeringWheelTurnRatio, which only rotates the in-game steering wheel mesh and does nothing if no mesh is assigned.

    Tuning by Wheel Type

    Direct drive (CSL DD, R9, Alpha, Simucube). Defaults are aimed here. Set wheelbaseTorque correctly, leave springEffectStrength and suspensionCenteringStrength at 0, and tune feel with damperHighSpeedFloor - it is the single knob that decides whether the wheel feels planted or loose at speed.

    Belt and gear wheels (T300, G29, G923). These have mechanical friction and less headroom. Raising springEffectStrength and suspensionCenteringStrength above 0 helps the wheel find centre, and lowering textureBudget keeps detail from eating the limited torque available for the main force.

    Clipping. If _compressionPct sits high in the debug readout, the soft clip is working constantly and detail is being squashed. Lower overallEffectStrength or the per-vehicle overallCoeff rather than raising wheelbaseTorque above the device's real figure.

    Diagnostics

    In play mode the inspector shows a Debug Values section:

    Readout Meaning
    _signedSatNm Signed steering-column torque in Nm. Use this to confirm polarity: turning right should give a torque pushing back toward centre.
    _primaryForcePct Share of output coming from the self-aligning torque.
    _effectsForcePct Share coming from texture and secondary effects.
    _totalForcePct Total output as a percentage of full device torque.
    _compressionPct How hard the soft clip is compressing. Persistently high means you are asking for more torque than the device has.

    Troubleshooting

    Wheel Pulls Into the Turn Instead of Centering

    Output polarity is inverted for your device. Enable invertFFBOutput (Debug inspector mode - see the gotcha in Setup).

    Device Not Detected

    • Ensure Unity-DirectInput package is installed
    • Restart Unity after installation
    • Check that your device appears in Windows Game Controllers
    • Try disconnecting and reconnecting the device
    • Check there is only one DIInputManager in the scene

    Slow Enumeration

    DirectInput device enumeration can occasionally take up to 60 seconds due to a Windows bug. USB Audio DACs and certain keyboards (e.g. Corsair) can cause this. Try disconnecting non-essential USB devices.

    Force Feedback Not Working

    • Verify overallEffectStrength is greater than 0
    • Check wheelbaseTorque matches your wheel's actual torque output
    • Ensure the vehicle has at least 2 front wheels with WheelControllers
    • Check DIInputManager shows your device as FFB-capable

    Forces Cut Out After a Pause or Script Recompile

    Expected. Output fades to zero if the physics step stops publishing for 250 ms, which covers pausing, entering a domain reload, and main-thread stalls. It recovers on its own once the game resumes.

    Wheel Feels Numb or Over-Damped

    Lower damperHighSpeedFloor first. If the wheel then oscillates around centre, raise it back slightly rather than adding spring or centring force.

    Extending the Provider

    If you are modifying FFBInputProvider, the output loop runs on its own thread. No UnityEngine API may be called from it - not Time, not AnimationCurve.Evaluate, not any UnityEngine.Object access, not Debug.Log. Mathf is safe because it is pure static maths. Anything else must be sampled during FixedUpdate and passed across in the snapshot struct the thread reads. Breaking this rule hangs the editor rather than producing a warning.

    Requirements

    • Unity-DirectInput package (https://github.com/imDanoush/Unity-DirectInput.git)
    • Windows 10/11 (DirectInput is Windows-only)
    • DirectInput-compatible steering wheel with force feedback
    • Vehicle must have at least 2 front wheels with WheelControllers
    In this article
    Back to top Copyright © NWH - Vehicle Physics, Aerodynamics, Dynamic Water Physics