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.
VehicleComponent
is a building block of NWH Vehicle Physics 2.
VehicleController
is a collection of VehicleComponent
s, which includes VehicleModule
s, Effects
and SoundComponent
s - both of which inherit from VehicleComponent
.
For class reference click here.
Each VehicleComponent
can:
VehicleComponent
that is enabled is updated.isOn
can be used instead.lodIndex
value is lower than vehicleController.activeLodIndex
it will be enabled, otherwise it will be disabled. lodIndex
to a value less than 0 to ignore LODs.
VehicleComponent
s that have isOn
set to false
are disabled and can not be enabled by LODs.
Turning components off should be used for components that will never be used.
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.
Enabled
button is greyed out as the LODs determine if the component will be enabled or disabled.VehicleComponent
on each VehicleController
, a ScriptableObject
StateSettings
was introduced.StateSettings
for each vehicle can be assigned under VehicleController ⇒ Settings tab. StateSettings
on State Settings page.
To change VehicleComponent
state through scripting following can be done:
myVehicleComponent.IsEnabled= myBoolValue; myVehicleComponent.IsOn = myBoolValue; myVehicleComponent.LodIndex = myIntValue;
Make sure to use Project Settings ⇒ Player ⇒ Input Handling ⇒ Both or multiple errors will pop up.
The input in NWH Vehicle Physics 2 centers around InputProvider
s. These are scripts that take user input (e.g. keypresses, mouse movement, gamepad input, etc.), process it and pass it on to the vehicles.
Multiple InputProvider
s can be present at the same time, meaning that MobileVehicleInputProvider
, InputSystemVehicleInputProvider
and SteeringWheelVehicleInputProvider
can all be present at the same time and the input will be combined from the mobile, keyboard/gamepad and steering wheel input.
The diagram above explains the path from input source to vehicle input state:
Auto Set Input
is set to false the state of the corresponding input for the vehicle in question will be set to the combined value of all inputs.Input > AutoSetInput
set to false the new input will be discarded. This happens in case the vehicle is inactive or the input is being set by some other script (e.g. AI).AutoSetInput
is enabled.VehicleInputProvider
(for vehicle-related input) or SceneInputProvider
(for scene-related input such as cameras). Therefore it is best to think about InputProviders as a standardized interface between different input methods and a vehicle.InputProvider
s are split into VehicleInputProviders and SceneInputProviders. VehicleInputProviders relay vehicle input (throttle, brakes, etc.) while SceneInputProviders take care of scene input (vehicle changing, camera changing, camera movement and the rest of the inputs not directly related to vehicle. One of each needs to be present (e.g. InputSystemVehicleProvider
and InputSystemSceneInputProvider
).InputProvider
s can be present in the scene (v1.0 or newer required). E.g. InputSystemProviders and MobileInputProviders can be used in the same scene. The resulting input will be a sum of inputs from all InputProvider
s in case of numeric inputs and logical OR operation of all inputs in case of boolean inputs. InputStates
struct and can be copied over from one vehicle to another. E.g. this is what is done when a trailer is connected to a towing vehicle.InputStates
make sure Auto Set Input
is set to false.
All input providers inherit from either VehicleInputProviderBase
or SceneInputProviderBase
, but differ in their implementation. To create a new input provider simply inherit from one of those two classes and implement the members.
When importing the asset for the first time this message will pop up:
Both Yes
or No
can be selected but it is important to set the Project Settings ⇒ Player ⇒ Input Handling to Both
afterwards. This way both new InputSystem and the old InputManager will work. If this setting is set to InputManager
only errors might appear as the demo scenes of the asset rely on InputSystem.
If a message This Unity Package has Package Manager dependencies. appears, click Install/Upgrade
.
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. |
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. |
InputProvider
for handling user input on desktop devices through keyboard and mouse or gamepad.
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.
When first importing NWH Vehicle Physics 2 the project will be missing required bindings. There are two ways to add those:
[UnityProjectPath]/ProjectSettings/InputManager.asset
file. To do so:To set up InputManager-based input in the scene add the following components to the scene:
Any vehicle that is present in the scene will now receive input from these providers.
When using DS4Windows, InputSystem will detect button presses twice.
Active Input Handling select
Input System Package (New)
or Both
- the latter in case your project still uses UnityEngine.Input
somewhere.InputSystemVehicleInputProvider
and InputSystemSceneInputProvider
to any object in your scene..inputactions
files. Save Asset
must be clicked for the changes to take effect.Since v1.7.1 NWH Vehicle Physics 2 also supports Rewired input.
Rewired Input Manager
to the scene. It already contains the Rewired InputManager
, as well as the RewiredVehicleInputProvider
and RewiredSceneInputProvider
needed for NVP2 control.InputSystemVehicleInputProvider
, InputManagerVehicleInputProvider
, InputSystemSceneInputProvider
and InputManagerSceneInputProvider
scripts 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.MobileVehicleInputProvider
and MobileSceneInputProvider
to the scene.UnityEngine.UI.Button
component and replace it with MobileInputButton
. MobileInputButton
inherits from UnityEngine.UI.Button
and adds hasBeenClicked
and isPressed
fields which are required for Mobile Input Provider
MobileVehicleInputProvider
and MobileSceneInputProvider
inspectors. Empty fields will be ignored.For more info visit SteeringWheelInputProvider page.
Since v1.0 multiple InputProvider
s 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 InputProvider
s (say to find out if a button was pressed on a keyboard):
<code>
float throttle = InputProvider.Instances[0].Throttle;
</code>
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.
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 - AutoSettable
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.
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
:
ExampleVehicleInputProvider
and make it inherit from VehicleInputProvider
class:public class ExampleVehicleInputProvider : VehicleInputProvider{}
GetThrottle()
.ToggleGUI()
which are optional and will be ignored if not implemented.false
, 0
or -999
in case of ShiftInto()
method.ExampleVehicleInputProvider
now can be added anywhere in the scene as the included InputSystemVehicleInputProvider
or InputManagerVehicleInputProvider
would 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.
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. }
NWH Vehicle Physics 2 uses different solver from NWH Vehicle Physics 1. Solver in NWH Vehicle Physics uses multiple ticks per one FixedUpdate
and is physically accurate. The only component that is approximated is the clutch and that is due to performance reasons.
Powertrain
in NWH Vehicle Physics 2 is a collection of Powertrain Components such as EngineComponent
, ClutchComponent
, DifferentialComponent
, etc.
PowertrainComponents
, except for WheelComponent
which always outputs to WheelController
.EngineComponent
which acts as a power source and Wheel Component
acts as a power sink. The components in-between determine how the power/torque will be transmitted.
The only setting available for solver is
Physics Quality
. Physics Quality
changes the number of ticks per one FixedUpdate:
* Low
- 8 ticks
* Medium
- 12 ticks
* High
- 16 ticks
* Very High
- 24 ticks
* Ultra
- 32 ticks
* Overkill
- 48 ticks
* Performance impact is directly proportional to the number of ticks. Powertrain
code is heavily optimized.
* Using very low values (<8) can result in low simulation fidelity and/or instability, especially if used with high power vehicles, high gear ratios or complex differential setups.
Since v1.4 physics quality can be adjusted under Settings tab by changing the number of physics substeps.
PowertrainComponent
is a base class for all powertrain components: EngineComponent
, ClutchComponent
, TransmissionComponent
, etc.
PowertrainComponent
s have the following common fields in the inspector:Name
- name of the component. Changing the Name
of a component will reset Output
on any components that are using that component.Inertia
- inertia of the component. Inertia of each component contributes to the total system inertia. How much depends on the clutch engagement and current gear ratio.Output
- Powertrain Component
to which the torque is forwarded. In cases such as Differential Component
there can be multiple outputs (e.g. left and right wheel).name
field on component will reset all the Output
s on other PowertrainComponent
s that use that component as an output.Inertia
will will make the component spin up slower if the same torque is applied.Inertia
of WheelComponent
is calculated from WheelController
s mass and radius settings.
Inertia
must always be larger than 0!
Higher engine inertia results in an engine that is harder to stall. Such engine will also take longer to spin up.
Power curve represents engine power across its RPM range.
Both 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
.
Idler circuit tries to keep RPM at Idle RPM
when there is no user input.
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. If too low Starter Torque
is used or Starter RPM Limit
is lower than Stall RPM
of the engine, the engine will fail to start.
Cuts throttle to the engine when RPM reaches Rev Limiter RPM
for a duration of Rev Limiter Cutoff Duration
.
ForcedInduction
is a part of EngineComponent
. It can be used for both turbocharging and supercharging the vehicle. Power Gain Multiplier
adds power on top of the existing Max Power
so the vehicle with 100kW and Power Gain Multiplier
of 1.5 will actually produce 150kW.TurboWhistleComponent
and TurboFlutterComponent
. If forced induction is to be used just for the sound effects Power Gain Multiplier
should be set to 1.
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 TCS module which uses this mechanic to limit power when there is wheel spin.
ClutchComponent
is a mandatory Powertrain
component. It is always second in the Components
list.
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.Is Automatic
to use manual clutch.Clutch
axis - check Input section for more info on setting up axes.
PID controller is used to control Clutch Engagement
when Is Automatic
is true.
PID_Coefficient
can be adjusted to slow down or speed up clutch engagement.Has Torque Converter
is false Slip Torque
is used. Otherwise, clutch will use Torque Converter Slip Torque
. \\]Slip Torque
will result in grabby clutch.Slip Torque
values can result in torque spikes when clutch is suddenly released which can impact solver stability in extreme cases.TransmissionComponent
is a mandatory Powertrain
component. It is always third in the Powertrain.Components
list.TransmissionGearingProfiles
which can be used as an example. TransmissionGearingProfile
ScriptableObject
.Upshift RPM
, Downshift RPM
, Variable Shift Intensity
and Incline Effect Coeff
variables. Gear skipping is enabled (e.g. it is possible that the vehicle will shift from 1st to 3rd if conditions are right).Target Upshift RPM
and Target Downshift RPM
under the Shifting section of the TransmissionComponent
inspector. These values vary depending on the variables mentioned above.
Same as Automatic
but without gear skipping.
CVT
(and eCVT) transmissions have variable gearing ratio dependent on load.Shift
delegate is used for changing gears.To make shifting more realistic two timers have been added:
Shift Duration
- time Transmission
takes to change from one gear to another. During this time EngineComponent
's throttle is cut off. Works for all transmission types that shift gears.Post Shift Ban
timer. This field determines minimum time between two shifts. Used to prevent transmission for shifting too often. Only affects automatic transmission types.
Transmission will only shift in automatic mode if ALL of the following conditions are met and after they have been met for Shift Check Cooldown
seconds:
No Wheel Spin
- longitudinal slip on all wheels is less than Longitudinal Slip Threshold
(Settings tab)No Wheel Skid
- lateral slip on all wheels is less than Lateral Slip Threshold
(Settings tab)No Wheel Air
- none of the wheels are in the air.Clutch Engaged
- clutch is fully engaged.External Shifts Checks Valid
- list of ShiftCheck
delegates. All external shift checks must be valid for transmission to be able to shift.
You can check the state of shift conditions in the inspector:
TransmissionGearingProfile
is a ScriptableObject
that determines the gear ratios for the TransmissionComponent.
Forward Gears
list contains all forward gear ratios in order from 1st gear up. In the example above:Reverse Gears
list contains all reverse gear ratios. Multiple reverse gears can be added, e.g.Final Gear Ratio
is the coefficient by which all the gears are multiplied. This is very similar to differential gear ratio and can be used to tune the gearing without having to adjust the gearing between individual ratios.
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.
Torque in open differential is equally split between the left output and right output.
Locked differential keeps both outputs rotating at same angular velocity.
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.
Can be used to assign an external differential delegate function.
WheelComponent
is a PowertrainComponent
. It acts as a torque sink and can not output to another PowertrainComponent
WheelComponent
should not be mixed up with WheelController
which is a replacement for Unity's WheelCollider
.Belongs To
field determines to which WheelGroup the WheelComponent
belongs to. This will determines values such as braking and steering coefficients and geometry.Inertia
field gets auto-calculated from assigned WheelController
's mass and radius.Steer Coefficient
determines how much the wheel will steer depending on input. In general cars would have Steer Coefficient
of 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.Ackerman Percent
- check this Wikipedia link for more info about Ackerman Steering setup. 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:Brake Coefficient
- amount of brake torque used as a percentage of Brakes
⇒ Max Torque
.Handbrake Coefficient
- amount of brake torque applied when handbrake is activated.Toe Angle
- toe angle in degrees.Caster Angle
- caster angle in degrees.Camber At Top
and Camber At Bottom
- camber angle in degrees at the top (fully compressed) and the bottom (fully relaxed) of suspension travel. Current value will be an interpolated result between the two.
Axle settings are used only if there are exactly two wheels in the WheelGroup
.
Anti Roll Bar Force
- force that imitates anti-roll bar in a vehicle. Before increasing value it is best to make sure that the center of mass of the vehicle is correct as too high center of mass can result in unstable vehicle. Too high values can introduce jitter to the vehicle as the ARB will try to equalize the suspension travel of both wheels Is Solid
- Imitates solid axle and auto-adjusts camber to make sure that both wheels always stay parallel to each other.
Sound system in NVP2 consists of SoundManager
and multiple SoundComponent
s. Disabling SoundManager
also disables all the SoundComponent
s.
SoundComponent
(type of Vehicle Component
) is responsible for one sound, e.g. EngineRunningComponent
or EngineStartingComponent
.AudioSource
s are not added manually but are instead generated by the script when scene is started. Some SoundComponent
s can have more than one AudioSource
- e.g. wheel related SoundComponent
s have one AudioSource
for each wheel.VehicleAudioMixer.mixer
) can be used.Mixer
field must have AudioMixer
assigned. By default VehicleAudioMixer
will be used.
SoundComponent
inherits from VehicleComponent
.
Check VehicleComponent page for more info.
SoundManager
is the main class for handling sound. It contains all the global sound settings and also manages individual SoundComponents.
Also check Sound page.
Master settings affect all the SoundComponent
s
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.
Velocity Magnitude Effect
.Pitch Randomness
field.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.
AudioSource
of EngineRunningComponent
is positioned at Exhaust Position
(Settings tab).Distortion affects volume so when high levels of distortion are used it is usually a good idea to reduce volume range proportionately.
EngineStartComponent
plays while the starter is active. AudioSource
of EngineStartComponent
will be positioned at Settings ⇒ Engine Position
.Imitates high-pitched sound of forced induction.
AudioSource
of TurboWhistleComponent
is positioned at Settings ⇒ Engine Position
.
Effect system makes use of VehicleComponents and therefore each Effect
can be turned on or off, be enabled or disable or have LOD set.
Effect
s with manager in the name manage multiple instances of the effect, usually one for each wheel - e.g. skidmarks or surface particles.
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.
Quad
s perpendicular to each other. Move them to the location of the exhaust.Quad
s.Particles/Standard Unlit
(Unity 2019) or equivalent shader with Transparent
rendering and Multiply
color mode. The included example on Sports Car prefab can be copied. Assigning one of the included flame textures will show if the rotation of the Quad
is correct. Rotate Quad
if needed.MeshRenderer
s from the newly created Quads to the ExhaustFlash
⇒ Mesh Renderers
list.To make flames look more convincing a random texture is assigned to each Quad on each flash. A number of default textures is included.
Flash Textures
list.
ExhaustSmoke
controls exhaust ParticleSystem
color, size and emission speed. It interpolates between NormalColor
and SootColor
based on engine state.
ParticleSystem
s at vehicle exhaust position. Prefab of pre-configured ParticleSystem
comes with the asset (Effects > Particles > Prefabs).ParticleSystem
s to the Particle Systems
list inside ExhaustSmoke
inspector.
LightsManager
is tasked with turning VehicleLight
s on or off depending on user input.
VehicleLight
is a collection of LightSource
s. When the light is turned on all LightSources
are turned on and vice versa.
One vehicle light source. Can be a Light
or emissive Mesh
.
Light
is selected as Type
any Unity Light
can be assigned. It will be turned on and off according to user input.Mesh
is selected as Type
any Mesh
with Standard
shader can be used. It's Emission
field will be toggled to imitate a working light. Since this does not emit enough light to be a headlight usually another light source is used in tandem, this one with SpotLight
assigned.
For an emissive mesh light to work it needs to be a separate object. If the model does not come with lights and blinkers as separate objects these will need to be separated in 3D modelling software such as Blender (free, open source).
When using Mesh
light source make sure to tick the Emission
checkbox on the material. This lets Unity know that this variant of the material is in use and should be included in the build.
Skidmarks are generated when wheel skids / slips over a surface.
Max Marks Per Section * 2
. Min Distance
is the distance a wheel needs to travel before a new mark is created.Max Marks Per Section
- similar to the old snake game. To make this transition smooth Fade Over Distance
can be enabled or Peristent Skidmarks
can be used. Check the section below for more info.GrounOffset
needs to be increased.Longitudinal Slip Threshold
and Lateral Slip Threshold
from vehicle settings tab are used.SurfacePreset
to get the settings for the current surface type.Max Marks Per Section
size.Peristent Skidmark Destroy Distance
.
SurfaceParticleManager
creates and manages particles based on current SurfacePreset
settings.
ParticleSystems
.Lateral Slip Threshold
and Longitudinal Slip Threshold
under Settings tab determine the lowest wheel slip threshold needed for wheel to be considered to be slipping. This affects particle effects.
GroundDetection
is one of the most important aspects of NWH Vehicle Physics. It determines which WheelFrictionPreset
will 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 Terrain
texture indices and object tags so it is very important how many textures there are assigned to the Terrain
and in which order.
To prevent having to change the settings across all the vehicles GroundDetectionPreset
ScriptableObject
was introduced in NWH Vehicle Physics 2.
Terrain
s in one scene.GroundDetection
runs 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 time GroundDetection
registers it.
GroundDetectionPreset
is a ScriptableObject
that determines which SurfacePreset
will be used on which terrain texture and object. This is done through SurfaceMap
s.
SurfaceMap
tells GroundDetection
which SurfacePreset
to use for which terrain texture and/or object tag.
GroundDetection
runs a check for each WheelComponent
to determine which surface that WheelComponent
is on. This is done by checking all the assigned SurfaceMap
s in order and if any SurfaceMap
has a matching terrain texture index in Terrain Texture Indices
list, or the object the wheel is on has the tag from Tags
list, Surface Preset
will be assigned to that WheelComponent
.
Adding a gravel SurfaceMap
will be used as an example.
SurfaceMap
by clicking on +
button on the bottom of the list.Terrain Texture Indices
list.GravelRoad
) to those objects and add it to Tags
list.
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.
Create ⇒ NWH Vehicle Physics ⇒ Surface Preset
. This will create a new SurfacePreset
ScriptableObject
in the current directory.Friction Preset
. This is a ScriptableObject
with settings for tire friction so that WheelController
can adjust its behavior according to the surface type. With asset come multiple Friction Preset
s so just pick one of those for now.Skidmark Material
will be used on generated skidmarks while the wheel is on this surface type.Slip Factor
determines 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.ParticleType
- Smoke
should be used for hard surfaces (asphalt, concrete), Dust
for dusty surfaces (gravel, sand). The difference between the two is in the way the emission rates are calculated. If Smoke
is selected this will be related to the wheel slip while it will depend on vehicle speed for Dust
.Particle Life Distance
is used to calculate ParticleSystem
's Start Lifetime
. The faster the vehicle is going the shorter the lifetime of the particles will be.Max Particle Emission Rate Over Distance
determines amount of particles emitted over distance of one meter.Max Particle Lifetime
determines the absolute maximum time a particle can be alive. When still this value determines how long the particle lives. When moving Particle Life Distance
is used instead.
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).
SkidSound
and SurfaceSound
settings are used to set WheelSkidComponent
and WheelTireNoiseComponent
SoundComponents values for current surface.
If the vehicle is not steering also check WheelGroup settings. It is most likely that all WheelGroup
s have SteerCoefficient
set to 0 which means no axles will steer.
Maximum Steer Angle
- angle in [deg] that the wheels can achieve. Multiplied by the WheelGroup
SteerCoefficient
to get the final axle steer angle.Use Direct Input
- if ticked the raw input is fetched from the InputProvider
s 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.Maximum Steer Angle
is multiplied to get the final steer angle.Speed Sensitive Smoothing Curve
- determines the smoothing applied to the steering input in relation to vehicle speed.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.Controls brakes.
Max Torque
as it might introduce jitter. Usually the best value is the one just above the point where the wheels lock up under heavy braking.Smoothing
can be used to make braking more progressive when using binary input.Related:
DamageHandler
deforms the meshes on the vehicle (skinned meshes are not supported due to performance reasons).
Deformation Vertices Per Frame
field. 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 Strength
and Deformation Randomness
all 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 Threshold
is the minimum deceleration value needed for collision to be registered by DamageHandler
.Validate Setup
- when clicked Validate()
function gets called on VehicleController
and all of its VehicleComponent
s. If there are any issues with the vehicle setup a message will pop up in the console.
Physical properties section mostly relates to the vehicle Rigidbody
. Rigidbody
properties are set by VehicleController
at start. Changing them after VehicleController
has been initialized will have no effect. If you need to do that change the values of the Rigidbody directly from your script.
Vehicle Dimensions
- dimensions of the vehicle in meters. Width x Height x Length. Has impact on aerodynamic drag calculation if Aerodynamics
module is active.Inertia Tensor
- inertia tensor of the vehicle. Unity calculates inertia of Rigidbodies as if they are solid (i.e. have uniform density). Cars have a lot of quite heavy parts and a lot of empty space and therefore custom inertia calculation is required. Click Calculate Inertia Tensor button to automatically calculate inertia. If you want the vehicle to have more rotational inertia around any of the three rotation axes increase the value for that axis. I.e. increasing Y will make the vehicle resist steering more.Center Of Mass
is a point relative to the vehicle's coordinate system at which the center of mass of the Rigidbody will be. There is a gizmo of a weight at the center of mass position. Longitudinal positioning of center of mass heavily affects vehicle handling. Avoid using high centers of mass. Calculate Center Of Mass
will auto-center center of mass to be exactly between the wheels. This is a good starting point but does not guarantee the best weight distribution and should be manually tweaked for best results.Multiplayer Instance Type
determines if the current vehicle instance is Local
(i.e. controlled by a local player) or Remote
(i.e. controlled by another player over network).Longitudinal Slip Threshold
and Lateral Slip Threshold
determine the amount of slip a wheel can have before it is considered to be slipping/skidding. Most sounds and effects will not trigger while the slip value is below the threshold value.Use Low Speed Fix
- if true drag will be added to Rigidbody when vehicle velocity is ~0 to prevent vehicle from creeping on slopes due to the nature of slip calculation.
NWH Vehicle Physics 2 is a collection of VehicleComponent
s. 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.
VehicleController
.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
drawer. Go to Modules
tab of VehicleController
to see all of the available modules. This is to avoid cluttering the inspector with a multitude of different editors. Modules can also be filtered by category to make navigation easier.
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.
To add a module use:
myVehicleController.moduleManager.AddModule<MyModuleWrapperType, MyModuleType>();
Example (adding an ABSModule):
ABSModule absModule = myVehicleController.moduleManager.AddModule<ABSModuleWrapper, ABSModule>();
To get a module use:
myVehicleController.moduleManager.GetModule<ModuleType>();
Example (getting ABSModule):
ABSModule absModule = myVehicleController.moduleManager.GetModule<ABSModule>();
Alternatively, module can be retrieved through MonoBehaviour. The next snippet does exactly the same as the snippet above but might be more practical in some cases:
MyModule module = myVehicleController.GetComponent<MyModuleWrapper>().module as MyModule;
To remove a module use:
myVehicleController.moduleManager.RemoveModule<ModuleWrapperType>();
Example (removing ABSModule):
myVehicleController.moduleManager.RemoveModule<ABSModule>();
Since modules inherits from VehicleComponent they also work on the same principle:
myModule.Enable();
myModule.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;
For class reference click here.
Scripts ⇒ Vehicle ⇒ Modules ⇒ ModuleTemplate
folder there is an empty example module. Copy ModuleTemplate
to create a starting point for a new module.ModuleDrawer
(a type of CustomPropertyDrawer
) placed in Editor
folder.ModuleWrapper
ModuleDrawer
which 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 with ModuleManager
drawer.
ModuleManager
is a VehicleComponent
that manages VehicleModule
s.
For more info on Modules check Modules page.
Frontal Cd
and Side Cd
(Cd = coefficient of drag) fields. Data for different vehicles is available here.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.
Downforce Point
s should be below the WheelController
position, 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 Points
and Max Downforce Speed
.Max Downforce Speed
at which it reaches Max Force
value.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 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.
Module containing a collection of assists aimed at achieving arcade-like behavior from the vehicles. Current functionality:
Adds artificial steer torque to the vehicle, independent of the tire grip. This helps rotate the vehicle.
Prevents the vehicle from drifting over the set angle, effectively preventing spin-outs.
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
.
Amount
indicates the amount of fuel currently in the tank while Capacity
indicates maximum tank capacity.
NOS (Nitrous Oxide System) module.
SoundComponent
which imitates hiss caused by releasing highly pressurised NOS from the bottle.ExhaustFlash
effect is enabled it will be active while NOS is active.
TrailerModule
works in tandem with TrailerHitchModule
. VehicleController
that has TrailerModule
is able attach to a VehicleController
that has TrailerHitchModule
.
TrailerHitchModule
and TrailerModule
.Attachment Point
is the point at which the trailer will be attached to the towing vehicle.Trailer Stand
is 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.Synchronize Gear Shifts
is 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.
VehicleController
with TrailerHitchModule
can attach a VehicleController
with TrailerModule
as a trailer.
TrailerHitchModule
and TrailerModule
can be present on one vehicle at the same time.AttachmentPoint
is the point at which the trailer will be attached. The trailer will be moved so that both trailer and hitch AttachmentPoint
s are at the same position. This is where the physics joint gets created.Also check Trailer module.