Vehicle Controller Manual
Before starting with detailed vehicle setup it is recommended to check out Quick Start guide as this page assumes a minimal working setup has been done.
If making an open-world game with a large-scale map (> ~4000 units), the shifting origin is required (not only for this asset, but in general with game engines that use floating point precision). Explanation.
Vehicle Component
VehicleComponent is a building block of NWH Vehicle Physics 2.
VehicleController is a collection of VehicleComponents, which includes VehicleModules, Effects and SoundComponents - both of which inherit from VehicleComponent.
State
Enabled / Disabled
VehicleComponentthat is enabled is updated.- Disabled components are not initialized until they get enabled for the first time.
- Disabling a
ManagerVehicleComponentsuch asSoundManager,EffectsManager,ModuleManagerorPowertrainalso disables the childVehicleComponents.
LOD Index
- If the component's
lodIndexvalue is lower thanvehicleController.activeLodIndexit will be enabled, otherwise it will be disabled. - Set
lodIndexto a value less than 0 to ignore LODs. - If adjusting LODs through inspector click on the currently active LOD to disable LOD system.
State Bar
Each VehicleComponent has a state bar which is visible in play mode:
This is where the state of the VehicleComponent can be checked and changed. Note that changing the state through state bar only affects runtime values and will revert after exiting play mode. The state bar is intended for previewing the current state and testing different values during run-time. For persistent state check StateSettings.
Using the State Bar
- Click on “On” button to turn the component on or off.
- Click on “Enabled” button to enable or disable the component.
- Click on any of the LOD numbers to set LOD. Click again on the same number to disable LODs. Component will be enabled if the current LOD number is green, and disabled if it is red. When LODs are active
Enabledbutton is greyed out as the LODs determine if the component will be enabled or disabled.
State Settings
- To prevent having to adjust the states of each
VehicleComponenton eachVehicleController, aScriptableObjectStateSettingswas introduced.
StateSettingsfor each vehicle can be assigned under VehicleController ⇒ Settings tab.
- More about
StateSettingson State Settings page.
Scripting
To change VehicleComponent state through scripting following can be done:
myVehicleComponent.LodIndex = -1; // IMPORTANT! Setting this to -1 disables the
// LODs which otherwise override the enabled/disabled setting.
myVehicleComponent.VC_Enable();
myVehicleComponent.VC_Disable();
- All the
VehicleComponentinitialization and update functions start with theVC_prefix to prevent confusion with Unity callbacks, e.g.VC_InitializeorVC_FixedUpdate.</wrap>
Input
Ensure you use Project Settings ⇒ Player ⇒ Input Handling ⇒ Both, or multiple errors may occur.
Input Concept
The input in NWH Vehicle Physics 2 revolves around InputProviders. These scripts obtain user input from different sources such as InputSystem or Rewired (e.g. keypresses, mouse movement, gamepad input, etc.), process it, and pass it on to the vehicles.
Multiple InputProviders can coexist, allowing for e.g. MobileVehicleInputProvider, InputSystemVehicleInputProvider, and SteeringWheelVehicleInputProvider to be present simultaneously. Input from all InputProviders is combined.
Input Retrieval
The diagram above illustrates the path from the input source to the vehicle input state:
- Input is obtained from hardware through Input Sources (green). This can be input from any method available in Unity. In this example, InputManager (old/standard Unity input), touchscreen/sensors (mobile input), and LogitechSDK for steering wheel input are used.
- InputProviders pass this input to the vehicle (VehicleController.InputHandler). Input from all sources is combined and processed based on settings for the specific vehicle.
- If
Auto Set Inputis set to true, the state of the corresponding input for the vehicle in question will be set to the combined value of all inputs. - If the VehicleController has
Input > AutoSetInputset to false, the new input will be discarded. This occurs when the vehicle is inactive or when the input is set by another script (e.g., AI).
Notes
- A single InputProvider supplies input for all vehicles, so it is recommended to have only one InputProvider of a particular type (e.g., one desktop and one mobile input provider, allowing vehicles to receive both desktop and mobile input simultaneously).
- Input providers only provide input; they do not set it. Vehicles acquire input from input providers if
autoSetInputis enabled on them. - All InputProviders inherit from either
VehicleInputProvider(for vehicle-related input) orSceneInputProvider(for scene-related input, such as cameras). Thus, it's best to consider InputProviders as a standardized interface between different input methods and a vehicle. InputProviders are divided into VehicleInputProviders and SceneInputProviders. VehicleInputProviders transmit vehicle input (throttle, brakes, etc.), while SceneInputProviders handle scene input (vehicle changing, camera changing, camera movement, and other inputs not directly related to the vehicle). One of each is necessary (e.g.,InputSystemVehicleProviderandInputSystemSceneInputProvider).- Input is stored inside the
InputStatesstruct and can be copied from one vehicle to another if needed. For example, this is done when a trailer is connected to a towing vehicle. - To manually set the
InputStates, ensureautoSetInputis set to false.
Available Bindings
Vehicle Input Provider Bindings
Out of the box gamepad bindings are only available for InputSystem.
| Name | Type | Keyboard Defaults | Gamepad Defaults | Description |
|---|---|---|---|---|
Steering | axis [-1,1] | A/D | Left Stick - Left/Right | Steering. |
Throttle | axis [0,1] | W | Left Stick - Up, Right Trigger | Throttle. |
Brakes | axis [0,1] | S | Left Stick - Down, Left Trigger | Brakes. |
Clutch | axis [0,1] | Manual clutch. 0 for disengaged and 1 for engaged. | ||
Handbrake | axis [0,1] | Space | B (Xbox) / Circle (PS) | |
EngineStartStop | Button | E | ||
ShiftUp | button | R | Right Shoulder | |
ShiftDown | button | F | Left Shoulder | |
ShiftIntoR1 | button | ` | Shift into 1st reverse gear. | |
ShiftIntoN | button | 0 | Shift into neutral. | |
ShiftInto1 | button | 1 | Shift into 1st forward gear. | |
ShiftInto[n] | button | 2,3,4,etc. | Shift into [n]th gear. | |
LowBeamLights | button | L | Y (Xbox) / Triangle (PS) | |
HighBeamLights | button | K | ||
HazardLights | button | J | ||
ExtraLights | button | ; | ||
LeftBlinker | button | Z | ||
RightBlinker | button | X | ||
Horn | button | H | ||
| Module Bindings | ||||
FlipOver | button | M | Used for FlipOverModule. | |
Boost | button | Left Shift | A (Xbox) / X (PS) | Used for NOSModule. |
Cruise Control | button | N | Used for CruiseControlModule. | |
TrailerAttachDetach | button | T | X (Xbox) / Square (PS) | Used for Trailer and TrailerHitch modules. |
Scene Input Provider Bindings
| Name | Type | Keyboard Defaults | Gamepad Defaults | Description |
|---|---|---|---|---|
ChangeCamera | button | C | Start | Changes camera. |
CameraRotation | 2D axis | Mouse Delta | Right Stick | Controls camera rotation. |
CameraPanning | 2D axis | Mouse Delta | Right Stick | Controls camera panning. |
CameraRotationModifier | button | Mouse - LMB | Right Stick Press | Enables camera rotation. |
CameraPanningModifier | button | Mouse - RMB | Left Stick Press | Enables camera panning. |
CameraZoom | axis | Mouse - Scroll | D-Pad Up/Down | Camera zoom in/out. |
ChangeVehicle | button | V | Select | Change vehicle or enter/exit vehicle. |
FPSMovement | 2D axis | WASD | Left Stick | Demo FPS controller movement. |
ToggleGUI | button | Tab | Toggles demo scene GUI. |
Input Methods
Input Manager (Old/classic)
- Type of
InputProviderfor handling user input on desktop devices through keyboard and mouse or gamepad. - Uses old Unity InputManager. For new projects, it is recommended to use the Unity's new InputSystem instead as InputManager is becoming obsolete.
Since v1.1 InputSystem package is required even if not used. If using the old/classic Unity input set Project Settings ⇒ Player ⇒ Input Handling to Both and proceed as normal. InputSystem package being present installed will not interfere with old/classic Unity input / InputManager.
Installation
When first importing NWH Vehicle Physics 2 the project will be missing required bindings. There are two ways to add those:
- Manually adding each entry to the Project Settings ⇒ Input following the input bindings table available here.
- Copying the contents of InputBindings.txt and appending them to the contents of the
[UnityProjectPath]/ProjectSettings/InputManager.assetfile. To do so:- Close Unity.
- Open InputManager.asset in Notepad/Notepad++/Visual Studio or any other text editor of your choice.
- Copy the contents of the provided InputBindings.txt file (Scripts ⇒ Vehicle ⇒ Input ⇒ InputProviders ⇒ InputManagerProvider ⇒ InputBindings.txt) and paste them at the end of the InputManager.asset. Make sure there are no empty lines between the existing content and the pasted content. Save the file.
- Open Unity. Check Project Settings ⇒ Input. The input bindings for NWH Vehicle Physics will appear towards the bottom of the list.
Scene Setup
To set up InputManager-based input in the scene add the following components to the scene:
- 'InputManagerVehicleInputProvider'
- 'InputManagerSceneInputProvider'
Any vehicle that is present in the scene will now receive input from these providers.
Input System (new)
- Since v1.1 NWH Vehicle Physics 2 has moved to InputSystem as a default input method.
- InputSystem v1.0 or higher is required. This is available in Unity 2019.3 or newer.
When using DS4Windows, InputSystem will detect button presses twice.
Installation
- Install 'Input System' package through Window ⇒ Package Manager
- Under Edit ⇒ Project Settings ⇒ Player ⇒ Other Settings ⇒
Active Input Handling selectInput System Package (New)orBoth- the latter in case your project still usesUnityEngine.Inputsomewhere.
Scene Setup
- Add
InputSystemVehicleInputProviderandInputSystemSceneInputProviderto any object in your scene. - Default bindings can be modified by double clicking on
.inputactionsfiles.Save Assetmust be clicked for the changes to take effect.
Rewired Input Provider
Since v1.7.1 NWH Vehicle Physics 2 also supports Rewired input.
Installation
- Download and import Rewired from the Unity Asset Store.
- Follow the Rewired install wizard. Make sure to leave both InputSystem and InputManager enabled. To use only InputManager, as recommended by Rewired, InputSystemVehicleInputProvider and InputSystemSceneInputProvider and their respective editor scripts need to be removed from the project first.
- With the Rewired imported and installed, double click on NWH ⇒ Vehicle Physics 2 ⇒ Scripts ⇒ Optional Packages ⇒ Input ⇒ Rewired to import files needed for Rewired/NVP2 integration.
- Open the newly imported Rewired folder and add
Rewired Input Managerto the scene. It already contains the RewiredInputManager, as well as theRewiredVehicleInputProviderandRewiredSceneInputProviderneeded for NVP2 control. - Remove any existing
InputSystemVehicleInputProvider,InputManagerVehicleInputProvider,InputSystemSceneInputProviderandInputManagerSceneInputProviderscripts from the scene to prevent input duplication. All these can technically be present at the same time but there are no benefits to it and duplicate inputs might happen.
Mobile Input Provider
- Add
MobileVehicleInputProviderandMobileSceneInputProviderto the scene. - Create a few UI ⇒ Button objects inside your canvas. Make sure that they are clickable.
- Remove the
UnityEngine.UI.Buttoncomponent and replace it withMobileInputButton.MobileInputButtoninherits fromUnityEngine.UI.Buttonand addshasBeenClickedandisPressedfields which are required forMobile Input Provider - Drag the buttons to the corresponding fields in the
MobileVehicleInputProviderandMobileSceneInputProviderinspectors. Empty fields will be ignored.
Steering Wheel Input Provider
For more info visit SteeringWheelInputProvider page.
Scripting
Retrieving Input
Since v1.0 multiple InputProviders can be present in the scene, meaning that their input has to be combined to get the final input result. To get the combined input use:
float throttle = InputProvider.CombinedInput(i => i.Throttle()); bool engineStartStop = InputProvider.CombinedInput(i => i.EngineStartStop());
Or to get the input from individual InputProviders (say to find out if a button was pressed on a keyboard):
float throttle = InputProvider.Instances[0].Throttle;
Manually Setting Input
Input in each vehicle is stored in InputStates struct:
myVehicleController.input.states
In case input should not be retrieved from user but from another script - as is the case when AI is used - autoSetInput should be set to false. This will disable automatic input fetching from the active InputProvider.
Input now can be set from any script:
myVehicleController.input.Horizontal = myFloatValue; // Using getter/setter.
myVehicleController.input.states.horizontal = myFloatValue; // Directly accessing states.
When using input generated by code (i.e. AI) it is usually handy to have access to a single axis throttle/brake. This can be done like so:
vehicleController.input.autoSetInput = false; // Tells the vehicle to stop retrieving input values automatically. vehicleController.input.Vertical = 0.5f; //Sets throttle to 0.5f, resets brakes. vehicleController.input.Vertical = -0.5f; //Sets brakes to 0.5f, resets throttle.
vehicleController.input.states.throttle is equal to vehicleController.input.Throttle. The latter is just a getter/setter for convenience.
The alternative to this is using the inputModifyCallback. It is executed just after the input is retrieved by the vehicle and allows modifying the inputs without having to worry about them being overwritten before the end of the frame:
myVehicleController.input.inputModifyCallback.AddListener(MyInputModificationFunction);
---
private void MyInputModificationFunction()
{
vc.input.Handbrake = 1f; // Apply handbrake by overriding the user input.
}
Custom InputProvider
If a custom InputProvider is needed it can easily be written. Custom InputProviders allow for new input methods or for modifying the existing ones. E.g. if the MobileInputProvider does not fit the needs of the project a copy of it can be made and modifications done on that copy. That way it will not get overwritten when the asset is updated.
Steps to create a new ''InputProvider''
- Create a new class, e.g.
ExampleVehicleInputProviderand make it inherit fromVehicleInputProviderclass:
public class ExampleVehicleInputProvider : VehicleInputProvider{}
- Override the methods that you want to use, e.g.
GetThrottle(). - The required methods are abstract and will need to be implemented. There are also virtual methods such as
ToggleGUI()which are optional and will be ignored if not implemented. - Methods that are not used should return
false,0or-999in case ofShiftInto()method. - The newly created
ExampleVehicleInputProvidernow can be added anywhere in the scene as the includedInputSystemVehicleInputProviderorInputManagerVehicleInputProviderwould be.
Example custom input script is below. Note that to reference NWH.Common.Input the script will either need to be generated inside Scripts > Input folder of the asset or referenced inside the project .asmdef file if the script is placed outside of the VehiclePhysics directory. For more info about assembly definitions check out the Import guide.
Example Custom VehicleInputProvider
using NWH.Common.Input;
using UnityEngine;
using UnityEngine.InputSystem;
/// <summary>
/// Example class for handling input.
/// </summary>
public class CustomVehicleInputProvider : VehicleInputProviderBase
{
public override void Awake()
{
base.Awake();
// Your initialization code here (if needed). Just a standard MonoBehaviour Awake().
}
public void Update()
{
// Your Update() code here (if needed). Just a standard MonoBehaviour Update().
}
public override Throttle()
{
// Return your custom value here, example:
return 0.5f; // Replace this line with e.g. player.GetAxis("Throttle") for Rewired.
}
public override Steering()
{
// Return your custom steering value here.
return 0.123f;
}
// ...and so on. Override the functions that you want to use. If you do not need Clutch() for example,
// do not override it.
}
Powertrain
About
- NWH Vehicle Physics 2 uses a physically accurate solver based on torque and angular velocity.
Powertrainin NWH Vehicle Physics 2 is a collection of Powertrain Components such asEngineComponent,ClutchComponent,DifferentialComponent, etc.
- Each component outputs to one or more
PowertrainComponents, except forWheelComponentwhich always outputs toWheelController. EngineComponentwhich acts as a power source andWheel Componentacts as a power sink. The components in-between determine how the power/torque will be transmitted.
Powertrain Component
The PowertrainComponent serves as a foundational class for all powertrain components, including EngineComponent, ClutchComponent, TransmissionComponent, and others.
Each PowertrainComponent possesses the following shared attributes in the Inspector:
Name- The label assigned to the component. Note that altering theNameof a component will reset the * *Outputfor any components that utilize that component.Inertia- Represents the inertia of the component. The inertia of each component contributes to the overall system inertia, which determines the difficulty of spinning the component up or down.Output- Specifies thePowertrain Componentto which torque is forwarded. For certain components, such as *Differential Component, multiple outputs may be present (e.g., left and right wheel).
Keep in mind the following:
- Modifying the
namefield of a component resets all theOutputs for otherPowertrainComponents that rely on that component as an output. - Increasing the
Inertiavalue will cause the component to spin up more slowly when the same amount of torque is applied. - The
Inertiaof aWheelComponentis determined by theWheelControllers mass and radius settings.
Always ensure that the Inertia value is greater than 0!
Engine Component
The engine acts as a source of power/torque and updates the components attached to it recursively with the generated torque.
When using the Electric engine, consider setting the output to the Transmission, bypassing the Clutch, as it is not needed.
Inertia
Higher engine inertia results in an engine that is harder to stall. The such engine will also take longer to spin up. Typical values:
- Sports car: 0.2
- Average car: 0.3-0.5
- Semi truck: 1-1.5
Power Curve
The power curve represents engine power across its RPM range.
X and Y values are normalized where X (0 to 1) represents RPM as a percentage of Rev Limiter RPM and Y (0 to 1) represents power as a percentage of Max Power.
Note that power and torque curves show the exact same data since the power is a function of torque and RPM, so knowing two of the three is enough. Since power curves are usually easier to find, NVP2 uses a power curve instead of a torque curve.
Idler Circuit
The Idler circuit tries to keep RPM at Idle RPM when there is no user input. This is done through throttle modulation so it is still possible to stall the engine if stallingEnabled = true.
Starter
Starter spins up the engine to try and reach the RPM at which the power generated by the engine is enough for it to spin by itself and overcome the losses. The amount of torque needed is automatically calculated based on the engine inertia, Power Curve, and the Start Duration value.
When Flying Start is enabled, the engine spins up instantly without running the starter. This is to give an illusion of the engine already having been started when the vehicle is woken up.
Rev Limiter
Cuts throttle to the engine when RPM reaches Rev Limiter RPM for a duration of Rev Limiter Cutoff Duration.
Forced Induction
ForcedInductionis a part ofEngineComponent. It can be used for both turbocharging and supercharging the vehicle.Power Gain Multiplieradds power on top of the existingMax Powerso the vehicle with 100kW andPower Gain Multiplierof 1.5 will actually produce 150kW.- Boost value affects sound components
TurboWhistleComponentandTurboFlutterComponent. If forced induction is to be used just for the sound effectsPower Gain Multipliershould be set to 1.
Power Modifiers
Power modifiers can be used through scripting to modify the power of the engine. These are functions that return a float which denotes an engine power coefficient. Example:
public float AddBoost()
{
if(boostIsActive)
{
return 1.5f; // Increases power for 50%.
}
}
...
myVehicleController.powertrain.engine.powerModifiers.Add(AddBoost);
This is a fictional example. A concrete example can be found inside the TCS module which uses this mechanic to limit power when there is wheel spin.
Clutch Component
ClutchComponent can be bypassed by setting the output of EngineComponent directly to the desired PowertrainComponent but this is not recommended as it will cause stalling in most cases.
Clutch Control
There are two things to note here: clutch engagement and clutch input. Clutch input controls the engagement through the Engagement Curve and is set either automatically, through user input, or scripting/inspector. It is best to think of the Clutch Input value as the pedal position, and the engagement as the “biting point” of the clutch.
Automaticsets the clutch engagement based on the input (engine) RPM.- The final engagement RPM, which is the RPM at which the clutch engagement is at 1 (100%), is the sum of
engagementRPM,throttleEngagementOffsetRPMandengagementRange.
UserInputtype can be used to give control to the user through a gamepad, steering wheel, etc.- When this control type is selected, the clutch is controlled through the
Clutchaxis - check Input section for more info on setting up axes.
Manualtype does not set the clutch value in any way and instead expects to be set externally, either through the inspector or through scripting.
Slip Torque
- When
Has Torque Converteris falseSlip Torqueis used. Otherwise, the clutch will useTorque Converter Slip Torque. \\] - Slip torque for an average clutch should be slightly higher than the maximum engine torque—usually a few hundred to a few thousand Nm.
- Too high
Slip Torquewill result in grabby clutch. - Using too high
Slip Torquevalues can result in torque spikes when the clutch is suddenly released which can impact solver stability in extreme cases.
- Values near zero will result in the engine spinning up as if the clutch is not engaged due to clutch slip.
Creep
- Some automatic transmissions have slight creep when engaged in D or R. This is normally caused by the torque converter (which is essentially a type of clutch) and it allows some of the torque from the engine to escape to the wheels.
Transmission Component
TransmissionComponentis a mandatoryPowertraincomponent. It is always third in thePowertrain.Componentslist.
- NWH Vehicle Physics uses gear ratios – just like the real transmission does.
- If gears are not set up properly the vehicle will not move.
Input Flipping
The asset uses W/S to select the movement direction by default. To use W/S as throttle/brake exclusively go to Control > Input and tick Swap Input In Reverse.
Gearing
- Gearing is assigned through the
gearslist and should be ordered from reverse, then neutral (always 0), then forward gear ratios. - Gear ratios can be adjusted during run-time.
Transmission Types
Manual
- In this type of transmission changing gears can only be done through user input. Check Input Setup for more info on input bindings.
Automatic
- Vehicle shifts gears based on the gear ratios and
Upshift RPM,Downshift RPM,Variable Shift IntensityandIncline Effect Coeffvariables. - Current
Target Upshift RPMandTarget Downshift RPMcan be seen under the under the Shifting section of theTransmissionComponentinspector, during runtime. These values vary depending on the variables mentioned above. IsSequentialmakes the transmission be able to shift only one gear up or down at the time. It has the same effect as ticking bothAllow Upshift Gear SkippingandAllow Downshift Gear Skipping.
CVT
CVT(and eCVT) transmissions have variable gearing ratio dependent on load.- One forward gear in Forward Gears list and one reverse gear in Reverse Gears list should be used. The value of the gear is the maximum gear ratio.
External
Shiftdelegate insideTransmissionComponentis used for changing gears.- This allows for external shifting logic.
- If the delegate is not assigned this option will result in no gear shifts.
Timing
To make shifting more realistic two timers have been added:
Shift Duration- timeTransmissiontakes to change from one gear to another. During this timeEngineComponent's throttle is cut off. Works for all transmission types.Post Shift Bantimer. This field determines minimum time between two shifts. Used to prevent transmission for shifting too often. Only affects automatic transmission types.
Shift Conditions
Transmission will only shift in automatic mode if all the ticked conditions conditions have been met for Shift Check Cooldown seconds:
Wheel Spin- longitudinal slip on all wheels is less thanLongitudinal Slip Threshold(Settings tab)Wheel Skid- lateral slip on all wheels is less thanLateral Slip Threshold(Settings tab)Wheel Air- none of the wheels are in the air.External Shifts Checks Valid- list ofShiftCheckdelegates. All external shift checks must be valid for transmission to be able to shift.
Transmission Gearing Profile
Transmission gearing profiles were deprecated in favor of a simple gears list.
Differential Component
DifferentialComponent is a type of PowertrainComponent that splits input torque between two or more outputs.
There can be multiple DifferentialComponents present on one vehicle and one differential can output to other differentials which is useful for 4WD setup with center differential.
Unused differentials should be removed. E.g. a front differential that none of the other powertrain components (transmission, other differentials, etc.) are outputting to should be removed, as only powertrain components that have a path to Engine are updated.
Differential Types
Open
Torque in open differential is equally split between the left output and right output.
Locked
Locked differential keeps both outputs rotating at same angular velocity.
Limited Slip
Replaces previous separate ViscousLSD and ClutchLSD options. Torque will be sent to the slower spinning wheel, keeping the wheels locked, up to the slip torque value.
External
Can be used to assign an external differential delegate function.
Configurations: 4WD / 2WD / etc.
To achieve a specific drivetrain configuration, different differential layouts can be used. For example:
- RWD: Set the Transmission output to a Differential whose outputs are rear wheels.
- FWD: Same as RWD, but with the Transmission outputting to a Differential whose outputs are front wheels. Remove any unused differentials.
- AWD/4WD: Can be achieved through three differentials; front, rear and center. The center differential should output to front and rear differentials, which then output to front and rear wheels, respectively.
- Adjustable: A configuration of differentials as in the AWD setup can be used, but with the center differential set to Open type. Adjusting the BiasAB slider on the center differential to 0 will make the car FWD and adjusting it to 1 will make it RWD, assuming the first output of the center differential is the front differential.
- 8×8 and similar: A trees of differentials can be built, which allows for setups such as 6×6, 8×8, etc. Example:
WheelComponent
WheelComponentis aPowertrainComponent. It acts as a torque sink and can not output to anotherPowertrainComponentWheelComponentshould not be mixed up withWheelControllerorWheelCollider.WheelComponentinstead interfaces between the powertrain an the wheel.Belongs Tofield determines to which WheelGroup theWheelComponentbelongs to. This determines values such as braking, steering and geometry.Inertiafield gets auto-calculated from assignedWheelController's mass and radius.WheelUAPIfield accepts any wheel controller/collider that uses the WheelUAPI abstract class as its base. The two shipped with the asset areWheelControllerandWheelColliderUAPI. This means that NVP2 can work with any wheel solution as long as it implements WheelUAPI. The reason whyWheelUAPIis not a pure interface is due to the Unity's serialization (or lack of it) for interfaces.
Wheel Group
Steering
Steer Coefficientdetermines how much the wheel will steer depending on input. In general cars would haveSteer Coefficientof 1 in front and 0 in the back, except for four wheel steering cars where rear axle usually steers opposite of the front so the value would be negative. Examples:1- 100% steering.0- no steering.-0.5- 50% steering in the opposite direction.
Add Ackerman- check this Wikipedia link for more info about Ackerman Steering setup.- Set automatically for 4-wheel (2×2) vehicles. Not used for motorcycles.
- When setting it manually, set to <0 for Reverse or Anti Ackermann or >0 for Ackermann steering. Field represents percent where 0.12 equals 12% of the steer angle. Following image describes the effect:
Brakes
Brake Coefficient- amount of brake torque used as a percentage ofBrakes⇒Max Torque.Handbrake Coefficient- amount of brake torque applied when handbrake is activated.
Geometry
Toe Angle- toe angle in degrees.
Caster Angle- caster angle in degrees.
- Note: Camber is no longer set through the WheelGroups, except in case of
isSolidbeing true, as in that case the camber is calculated so that the wheels always stay parallel to each other.- For fixed camber the camber is set through the WheelController. For dynamic adjustment of camber, the CamberController component can be attached to the WheelController.
Axle
Axle settings are used only if there are exactly two wheels in the WheelGroup.
Anti Roll Bar Force- deprecated,Force Application Point DistanceonWheelControllershould be used instead. Higher the value, lower the roll.Is Solid- Imitates solid axle and auto-adjusts camber to make sure that both wheels always stay parallel to each other.
Sound
About
Sound system in NVP2 consists of SoundManager and multiple SoundComponents. Disabling SoundManager also disables all the SoundComponents.
- Each
SoundComponent(type ofVehicle Component) is responsible for one sound, e.g.EngineRunningComponentorEngineStartingComponent. AudioSources are not added manually but are instead generated by the script when the scene is started. SomeSoundComponents can have more than oneAudioSource- e.g. wheel relatedSoundComponents have oneAudioSourcefor each wheel.- Each field affects only the vehicle to which the script is attached. To modify the audio output for all the vehicles VehicleAudioMixer (
VehicleAudioMixer.mixer) can be used.
Requirements
Mixerfield must haveAudioMixerassigned. By defaultVehicleAudioMixerwill be used.
Sound Component
SoundComponent inherits from VehicleComponent.
Check VehicleComponent page for more info.
Sound Manager
SoundManager is the main class for handling sound. It contains all the global sound settings and also manages individual SoundComponents.
Also check the Sound page.
Master Settings
Master settings affect all the SoundComponents
Equalizer
Each sound component belongs to one of the Audio Mixer groups: Engine, Transmission, SurfaceNoise, Turbo, Suspension, Crash or Other. Here you can add additional effects and modify the sound. One example of this is distortion which is added to the engine sound based on load through the Audio Mixer.
Blinker Component
Crash Component
- Sound of vehicle crashing.
- Supports multiple audio clips of which one will be chosen at random each time this effect is played.
- Volume is dependent on collision intensity. This can be adjusted through
Velocity Magnitude Effect. - Pitch is random. Randomness can be adjusted through
Pitch Randomnessfield.
Engine Fan Component
Engine Running Component
EngineRunningComponent is a SoundComponent responsible for the engine sound. A pitch based approach using a single pre-recorded engine sound clip is used along with filters to achieve relatively realistic sound.
Big upside of this approach is that only a single clip is required which is ideal for small game studios, as opposed to layering approach where usually tens of clips of engine at different loads, positions and RPMs are used to achieve the engine sound effect. Of course, the downside is that realism suffers.
If you need the layering feature please make a feature request through support.
AudioSourceofEngineRunningComponentis positioned atExhaust Position(Settings tab).
Notes
Distortion affects volume so when high levels of distortion are used it is usually a good idea to reduce volume range proportionately.
Engine Start Stop Component
EngineStartStopComponentplays while the starter is active.- First sound clip in the list will be used for engine starting sound.
- If the second clip is added to the list it will be played after the engine stops as an engine stopping sound.
- Starter settings can be adjusted under Powertrain ⇒ Engine tab.
AudioSourceofEngineStartComponentwill be positioned at Settings ⇒Engine Position.
Gear Change Component
Reverse Beep Component
Suspension Bump Component
Transmission Whine Component
Turbo Flutter Component
Turbo Whistle Component
Imitates high-pitched sound of forced induction.
- Can be used for both turbocharger and supercharger sound.
- Sound depends on EngineComponent.ForcedInduction.
AudioSourceofTurboWhistleComponentis positioned at Settings ⇒Engine Position.
Wheel Skid Component
Wheel Tire Noise Component
Effects
Effects Manager
Controls all the vehicle effects.
Effect system makes use of VehicleComponents and therefore each Effect can be turned on or off, be enabled or disable or have LOD set.
- All
Effects with manager in the name manage multiple instances of the effect, usually one for each wheel - e.g. skidmarks or surface particles.
Exhaust Flash
ExhaustFlash Effect is used to imitate flames shooting out of exhaust. The method to achieve this is identical to the one used for most muzzle flash in FPS games; that is a set of images gets enabled and disabled at rapid rate with different sprite and scale each time. This is a performant way to achieve the effect while avoiding particle effects.
Setup
Adding Quads
- Create and place two
Quads perpendicular to each other. Move them to the location of the exhaust. - Remove any colliders from
Quads. - Create a new material that uses
Particles/Standard Unlit(Unity 2019) or equivalent shader withTransparentrendering andMultiplycolor mode. The included example on Sports Car prefab can be copied. Assigning one of the included flame textures will show if the rotation of theQuadis correct. RotateQuadif needed.
- Assign the
MeshRenderers from the newly created Quads to theExhaustFlash⇒Mesh Rendererslist.
Assigning Textures
To make flames look more convincing a random texture is assigned to each Quad on each flash. A number of default textures is included.
- Assign textures to
Flash Textureslist.
Adding Point Lights
Exhaust Smoke
ExhaustSmoke controls exhaust ParticleSystem color, size and emission speed. It interpolates between NormalColor and SootColor based on engine state.
Setup
- Position
ParticleSystems at vehicle exhaust position. Prefab of pre-configuredParticleSystemcomes with the asset (Effects > Particles > Prefabs). - Assign the
ParticleSystems to theParticle Systemslist insideExhaustSmokeinspector.
LightsManager is tasked with turning VehicleLights on or off depending on user input.
Vehicle Light
Skidmark Manager
Skidmarks are generated when wheel skids / slips over a surface.
- Skidmarks are achieved by procedurally generating a mesh. One mark consists of two triangles and the number of triangles per one section can be calculated as
Max Marks Per Section * 2. Min Distanceis the distance a wheel needs to travel before a new mark is created.- Default behavior is to delete the oldest triangles as soon as number of marks reaches
Max Marks Per Section- similar to the old snake game. To make this transition smoothFade Over Distancecan be enabled orPeristent Skidmarkscan be used. Check the section below for more info. - If skidmarks are not visible or clip into the terain
GrounOffsetneeds to be increased. - To define when the wheel is slipping
Longitudinal Slip ThresholdandLateral Slip Thresholdfrom vehicle settings tab are used.
Surface-based Skidmarks
- Skidmarks use settings of currently active
SurfacePresetto get the settings for the current surface type.
- Also check GroundDetection page for more info.
Persistent Skidmarks
- Persistent skidmarks get stored into sections of
Max Marks Per Sectionsize. - Sections do not get destroyed as longs as the the player is under
Peristent Skidmark Destroy Distance. - Downside to this approach is that over time this will cause the number of triangles in the view-port to increase.
Surface Particle Manager
SurfaceParticleManager creates and manages particles based on current SurfacePreset settings.
- Particles are emitted on per-wheel basis. Total surface particle count is a sum of particle counts from all the wheels'
ParticleSystems. Lateral Slip ThresholdandLongitudinal Slip Thresholdunder Settings tab determine the lowest wheel slip threshold needed for wheel to be considered to be slipping. This affects particle effects.
Mirrors
Mirrors are set up through a combination of Cameras, RenderTextures and Materials with specific UV mapping.
Camera first renders its view to a RenderTexture which is assigned to a Material(any shader that supports albedo map will work). This Material has an UV map that corresponds to the surface of the vehicle mirror.
Possible setups are:
- Render each mirror with a separate
Camerato a separateRenderTexturewhich is assigned to a separateMaterial. Best visual quality but slow. - Using UV map that is split between the mirrors which means that each mirror gets only a part of the UV map, but this comes at a disadvantage that the interior of the vehicle can not be seen in rearview mirror since the camera needs to start rendering at the rear of the vehicle to prevent intersection with the vehicle mesh.
- Hybrid approach: one camera for rearview mirror and one camera for left and right mirrors.
Ground Detection
GroundDetectionis one of the most important aspects of NWH Vehicle Physics. It determines whichWheelFrictionPresetwill be used for calculating friction, which effects will be active, and which sounds will play. In short, it determines which wheel is on which surface.- Ground detection works based on
Terraintexture indices and object tags so it is very important how many textures there are assigned to theTerrainand in which order.
To prevent having to change the settings across all the vehicles GroundDetectionPreset ScriptableObject was introduced in NWH Vehicle Physics 2.
- NWH Vehicle Physics 2 supports ground detection with multiple
Terrains in one scene. GroundDetectionruns checks for a maximum of one wheel at a time. This is to improve on performance but it can introduce a small delay from the time the surface has been changed to the timeGroundDetectionregisters it.
Ground Detection Preset
Surface Map
SurfaceMaptellsGroundDetectionwhichSurfacePresetto use for which terrain texture and/or object tag.
GroundDetectionruns a check for eachWheelComponentto determine which surface thatWheelComponentis on. This is done by checking all the assignedSurfaceMaps in order and if anySurfaceMaphas a matching terrain texture index inTerrain Texture Indiceslist, or the object the wheel is on has the tag fromTagslist,Surface Presetwill be assigned to thatWheelComponent.
Adding a New Surface Map
Adding a gravel SurfaceMap will be used as an example.
- Add a new
SurfaceMapby clicking on+button on the bottom of the list. - Check on which texture positions are the gravel textures. In the image above that would be 5 and 7. Add those numbers to the
Terrain Texture Indiceslist. - If there are objects that should represent gravel in the scene, assign a tag (e.g.
GravelRoad) to those objects and add it toTagslist.
Surface Preset
SurfacePreset tells the VehicleController which settings to use for which surface.
This determines tire friction, the look of effects such as skidmarks and particle effects. It also changes sounds to match the surface.
Once set up, SurfacePreset can be used for different terrains, scenes or even across games since SurfacePresets do not carry any scene-specific fields.
Setup
- Right click on empty space in Project window and select
Create ⇒ NWH Vehicle Physics ⇒ Surface Preset. This will create a newSurfacePresetScriptableObjectin the current directory. - Assign a name to it for easier debugging later.
Friction
- Assign a
Friction Preset. This is aScriptableObjectwith settings for tire friction so thatWheelControllercan adjust its behavior according to the surface type. With asset come multipleFriction Presets so just pick one of those for now.
Skidmarks
- Adjust skidmark settings according to the surface type. More about skidmark settings on Skidmarks page.
Skidmark Materialwill be used on generated skidmarks while the wheel is on this surface type.Slip Factordetermines if the skidmarks are slip dependent. On soft surfaces such as sand this value should be 0 as the skidmarks/thread-marks should always be visible, no matter the slip. On hard surfaces such as asphalt skidmarks are only visible when there is wheel slip.
Dust/Smoke Particles
ParticleType-Smokeshould be used for hard surfaces (asphalt, concrete),Dustfor dusty surfaces (gravel, sand). The difference between the two is in the way the emission rates are calculated. IfSmokeis selected this will be related to the wheel slip while it will depend on vehicle speed forDust.Particle Life Distanceis used to calculateParticleSystem'sStart Lifetime. The faster the vehicle is going the shorter the lifetime of the particles will be.Max Particle Emission Rate Over Distancedetermines amount of particles emitted over distance of one meter.Max Particle Lifetimedetermines the absolute maximum time a particle can be alive. When still this value determines how long the particle lives. When movingParticle Life Distanceis used instead.
Chunk Particles
Chunk particles represent pieces of dirt, debris, sand or pebbles thrown behind the tire when there is wheel spin.
Depending on speed the lifetime of a a particle is calculated from Max Chunk Lifetime (when near still) or Chunk Life Distance (when moving).
Sounds
SkidSoundandSurfaceSoundsettings are used to setWheelSkidComponentandWheelTireNoiseComponentSoundComponents values for current surface.
Steering
If the vehicle is not steering also check WheelGroup settings. It is most likely that all WheelGroups have SteerCoefficient set to 0 which means no axles will steer.
Fields
Maximum Steer Angle- angle in [deg] that the wheels can achieve. Multiplied by theWheelGroupSteerCoefficientto get the final axle steer angle.Use Direct Input- if ticked the raw input is fetched from theInputProviders and not processed in any way (smoothing, etc.).Speed Sensitive Steering Curve- determines the steer angle coefficient in relation to speed. Useful for limiting steering at higher speeds to prevent spinning out.- X: Normalized speed (0 to 1) representing 0 to 50 m/s.
- Y: Steer angle coefficient by which the
Maximum Steer Angleis multiplied to get the final steer angle.
Speed Sensitive Smoothing Curve- determines the smoothing applied to the steering input in relation to vehicle speed.- X: Normalized speed (0 to 1) representing 0 to 50 m/s.
- Y: Smoothing, unitless. Generally in range of 0 to 0.5.
Linearity- maps the steering input value (X) to the new output value (Y). Useful for making steering less sensitive around center point.Degrees Per Second Limit- an amount of degrees the steering can be turned in one second. Lower number for heavy machinery (e.g. 80), higher for sports car (e.g. 250).Return To Center- steering will return to center once the input is released.
Related
Brakes
Tips:
- Avoid using excessively high
Max Torqueas it might introduce jitter. Smoothingcan be used to make braking more progressive when using binary input.- To adjust the brake or handbrake bias between axles, check the WheelGroups.
Related:
Damage Handler
DamageHandler deforms the meshes on the vehicle (skinned meshes are not supported due to performance reasons).
- Damage depends on deceleration at the moment of impact meaning that the faster the vehicle goes and the faster it stops on collision the more damage vehicle will take.
- As the vehicle gets damaged more and more engine power will reduce, some randomness will be added to the engine sound and if the crash happened near the wheel (all the wheel meshes need to be tagged as “Wheel”) wheel will start steering in a random direction degrading the handling of the vehicle. There is also a wheel wobble effect added.
- Mesh deformation that is the product of crashing is queue based. This means that only limited number of meshes will be deformed per frame. This value can be adjusted by changing the
Deformation Vertices Per Framefield. Higher value will result in deformation being completed in less frames while lower value will stretch the deformation over the higher number of frames – and will also cause less frame dropping. It is best to adjust this value to as high as it is possible without causing frame drops. This will depend on the device the final game will run on. Deformation Radius,Deformation StrengthandDeformation Randomnessall affect how the mesh will be deformed – how far the vertex can be moved from the original position, how much it will be moved for the given deceleration and how random the final result will be. Setting randomness to 0 will cause final mesh to be smooth and setting randomness to a high value will result in noisy looking mesh.Deceleration Thresholdis the minimum deceleration value needed for collision to be registered byDamageHandler.
Modules
NWH Vehicle Physics 2 is a collection of VehicleComponents. All aspects of it are a component - sound components, effect components, etc. - they all inherit from VehicleComponent. The only way that a module is different from an inbuilt component is that it can be added or removed as needed.
Modules carry over state system from the VehicleComponent which means that each module can be turned on or off, enabled or disabled or have LOD set.
Usage
- To add a module click on Add Component button at the bottom of the Inspector. Modules must be added to an object that already contains
VehicleController. - Each module is wrapped in a MonoBehaviour wrapper
ModuleWrapper. This is a way to work around lack of multiple inheritance in C#. So, to add a module just add its wrapper to the vehicle:
ModuleManager is a VehicleComponent that manages VehicleModules.
For more info on Modules check Modules page.
Module Wrapper
Each module is wrapped in a MonoBehaviour wrapper called ModuleWrapper. This is a way to get around lack of multiple inhertance in C#.
VehicleModule inherits from VehicleComponent, but it also needs to be serialized and for that it needs to be a MonoBehaviour. The new attribute [SerializeReference] has been present in Unity since 2019.3 and original implementation used that but the amount of bugs and lack of backwards-compatibility with older versions of Unity resulted in the wrappers being used instead.
Scripting
Adding a Module
Adding modules after vehicle initialization is not supported! Consider adding the module before entering play mode or immediately after adding the VehicleController (from scripting), and keeping them Disabled until needed.
To add a module use:
myVehicleController.gameObject.AddComponent<MyModuleWrapper>();
Example (adding an ABSModule):
myVehicleController.gameObject.AddComponent<ABSModuleWrapper>();
Getting a Module
Modules are VehicleComponents wrapped in MonoBehaviour containers (wrappers).
MyModule module = myVehicleController.GetComponent<MyModuleWrapper>().module as MyModule;
Removing a Module
To remove a module use:
Destroy(myVehicleController.GetComponent<MyModuleWrapper>());
If doing this during the runtime the module should simply be disabled instead. ModuleManager does not update the modules list during the runtime so removing the module will result in an error.
Enabling/Disabling a Module
Since modules inherits from VehicleComponent they also work on the same principle:
myModule.VC_Enable();
myModule.VC_Disable();
Note that disabling or enabling a module will have no effect while LODs are active for that module as the LOD system will override the manual settings while active.
To disable LODs for a module use:
myModule.LodIndex = -1;
Creating a New Module
- In the
Scripts ⇒ Vehicle ⇒ Modules ⇒ ModuleTemplatefolder there is an empty example module. CopyModuleTemplateto create a starting point for a new module. - Modules can be placed anywhere in the project and do not have to be in the same namespace as included modules.
- Directory structure of a module should be as following:
- Each module must have at least three files:
ModuleDrawer(a type ofCustomPropertyDrawer) placed inEditorfolder.- Module file(s).
ModuleWrapper
- Each module must have a property drawer. All module drawers inherit from
ModuleDrawerwhich uses NUI editor GUI framework (developed by NWH coding) to render custom property drawers and editors through simplified syntax. This also makes the created module compatible withModuleManagerdrawer.
ABS Module
Aerodynamics Module
Drag
- Drag depends on vehicle dimensions. Those can be adjusted under vehicle's Settings tab.
- Drag is calculated bot in longitudinal and lateral directions. Intensity of drag can be adjusted through
Frontal CdandSide Cd(Cd = coefficient of drag) fields. Data for different vehicles is available here.
Downforce
Downforce is calculated in a simplified fashion by applying downforce to a number of points over the vehicle. In the simplest form a single downforce point at the center of the vehicle can be used, or one point at the front and one point at the end of the vehicle.
- Vertical position of
Downforce Points should be below theWheelControllerposition, or even as low as the floor of the vehicle. This is because all the force is applied in a single point which, if applied too high, can cause the vehicle to snap oversteer when changing direction. - Downforce is not dependent on vehicle shape or dimensions. It is calculated through
Downforce PointsandMax Downforce Speed. - Downforce increases exponentially from 0 to
Max Downforce Speedat which it reachesMax Forcevalue. - Enable Gizmos to be able to see downforce points (red sphere).
Cruise Control Module
ESC Module
Motorcycle Module
Adds additional motorcycle balancing, steering and lean functionality to the NWH Vehicle Physics. The rest of the setup is similar to the conventional vehicle, just with two wheels and transmission outputting directly to the rear wheel, without the use of differentials.
Trikes can be implemented without this module as they do not require the additional functionality.
Field explanations can be seen by hovering over fields in the Unity inspector.
Lean Controller
Lean is implemented through a PID controller and is one of the more important settings of the module. It determines in which manner the vehicle will lean and balance. PID controller is required because the balancing is done through physics (AddTorque). The tuning of the said controller requires a bit of tweaking (adjustable at runtime) but the default settings should be adequate for a vast majority of motorcycles.
Arcade Module
Module containing a collection of assists aimed at achieving arcade-like behavior from the vehicles. Current functionality:
Steer Assist
Adds artificial steer torque to the vehicle, independent of the tire grip. This helps rotate the vehicle.
Drift Assist
Prevents the vehicle from drifting over the set angle, effectively preventing spin-outs.
Flip Over Module
If the vehicle gets flipped over FlipOverModule will flip it to be right side up again.
Flip Over Activationdetermines if the flip over will happen automatically, or if it will wait for userFlipOverinput once it detects that the vehicle is flipped over.Flip Over Typedetermines if the vehicle will get slowly rolled over or instantly flipped over in place.
Fuel Module
Module for simulating the fuel system in a vehicle. Fuel consumption gets automatically generated from engine efficiency (average ICE efficiency is used) and fuel energy content. Consumption can be adjusted through Consumption Multiplier.
- Prevents engine from running when out of fuel.
Amountindicates the amount of fuel currently in the tank whileCapacityindicates maximum tank capacity.
NOS (Nitrous Oxide System) module.
- Adds power to the engine.
- Affects engine sound by increasing volume.
- Has it's own
SoundComponentwhich imitates hiss caused by releasing highly pressurised NOS from the bottle. - If
ExhaustFlasheffect is enabled it will be active while NOS is active.
Rigging Module
Speed Limiter Module
TCS Module
Trailer Module
TrailerModule works in tandem with TrailerHitchModule. VehicleController that has TrailerModule is able attach to a VehicleController that has TrailerHitchModule.
- One vehicle can have both
TrailerHitchModuleandTrailerModule. Attachment Pointis the point at which the trailer will be attached to the towing vehicle. The script creates a SphereCollider trigger at this point which detects if the TrailerHitchModuleAttachment Pointis nearby.Attachment Pointneeds to be a child of theGameObjectcontaining theTrailerModule.Trailer Standis the object which will be enabled if the trailer is detached and vice versa. It prevents the trailer from tipping forward on trailers with only the back axle.- If
Synchronize Gear Shiftsis enabled the trailer object will be kept in the same gear. This allows for powered trailer or vehicles that are constructed out of two Rigidbodies.
Also check Trailer Hitch module.
Trailer Hitch Module
VehicleController with TrailerHitchModule can attach a VehicleController with TrailerModule as a trailer.
- Both
TrailerHitchModuleandTrailerModulecan be present on one vehicle at the same time. AttachmentPointis the point at which the trailer will be attached. The trailer will be moved so that both trailer and hitchAttachmentPoints are at the same position. This is where the physics joint gets created.Attachment Pointneeds to be a child of theGameObjectcontaining theTrailerHitchModule.- On initialization a SphereCollider trigger is created at the attachment point. This is used to detect if a TrailerModule is nearby. When there is overlap between the
TrailerModuleandTrailerHitchModuletriggers, pressing 'T' (default key mapping) will connect the trailer.
Also check Trailer module.










































































