Class WheelController
WheelController is a complete alternative to Unity's built-in WheelCollider, providing more realistic vehicle behavior, complete customization, and 3D ground detection across the entire bottom half of the wheel.
Key Features:
- 3D ground detection: The wheel has width and length, not just a single point in the middle
- Fully customizable via custom inspector: Adjust spring, damper, friction curves, geometry, etc.
- Pacejka friction model with support for different surfaces through FrictionPreset ScriptableObjects
- Adjustable camber, caster and rim offset
- Progressive suspension with customizable force curves
- Multi-threaded ground detection for optimal performance (approximately 0.03ms CPU time per wheel)
- Handles wheel visuals automatically (rotation and position)
- Suitable for various vehicle types: cars, trucks, motorcycles, tanks, etc.
Setup Requirements:
- Vehicle model should have Unity-correct rotation ([0,0,0]) and [1,1,1] scale
- WheelController GameObject should be a direct child of the vehicle's Rigidbody
- Position of the WheelController Transform acts as the suspension origin
- Visual meshes should be assigned to the Rotating and NonRotating containers
Performance Considerations:
- Ground detection occurs over the entire bottom half of the wheel, but not the top
- Collisions on the top half are handled by a native MeshCollider
- For best results, Time.fixedDeltaTime should be 0.01 (100Hz) or lower
- On mobile platforms, no higher than 0.02 (50Hz) is recommended
Namespace: NWH.WheelController3D
Assembly: NWH.WheelController.dll
Syntax
[DisallowMultipleComponent]
[DefaultExecutionOrder(100)]
public class WheelController : MonoBehaviour
Fields
| Edit this page View SourceANGULAR_VELOCITY_TO_RPM
Constant for converting angular velocity in rad/s to RPM.
Declaration
public const float ANGULAR_VELOCITY_TO_RPM = 9.55
Field Value
| Type | Description |
|---|---|
| float |
SLIP_THRESHOLD
Value above which the wheel is considered as slipping.
Declaration
public const float SLIP_THRESHOLD = 0.4
Field Value
| Type | Description |
|---|---|
| float |
absActive
True when ABS is actively reducing brake torque this frame.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[NonSerialized]
[Tooltip("True when ABS is actively reducing brake torque.")]
public bool absActive
Field Value
| Type | Description |
|---|---|
| bool |
absFrictionSlip
Current abs slip in friction direction.
Declaration
[Tooltip("Current slip in friction direction.")]
public Vector2 absFrictionSlip
Field Value
| Type | Description |
|---|---|
| Vector2 |
absFrictionSpeed
Abs speed at the point of contact with the surface.
Declaration
[Tooltip("Speed at the point of contact with the surface.")]
public Vector2 absFrictionSpeed
Field Value
| Type | Description |
|---|---|
| Vector2 |
activeFrictionPreset
Current active friction preset containing tire friction properties. FrictionPreset is a ScriptableObject that defines the friction curve parameters including stiffness, shape, peak, and falloff values for both longitudinal and lateral friction. Different presets can be used for different surfaces (asphalt, gravel, ice, etc.).
Declaration
[SerializeField]
[Tooltip("Current active friction preset containing tire friction properties. Different presets can be used for different surfaces.")]
public FrictionPreset activeFrictionPreset
Field Value
| Type | Description |
|---|---|
| FrictionPreset |
aligningMoment
Self-aligning torque (Mz) from tire deformation in Newton-meters [Nm]. Calculated from lateral force and pneumatic trail. Positive values create clockwise rotation (viewed from above) when wheel is steered right. Used for force feedback steering calculations.
Declaration
[ShowInTelemetry(-100, 100, "0.0", "Nm", 1)]
[NonSerialized]
[Tooltip("Self-aligning torque from tire deformation. Used for FFB steering.")]
public float aligningMoment
Field Value
| Type | Description |
|---|---|
| float |
applySuspensionAtContactPoint
Applies suspension force at the ground contact point instead of the wheel center, matching friction. Removes the moment arm that flips/launches the car when it bottoms out with forward velocity (the wheel pitches so the center and contact no longer line up with the normal).
Declaration
[Tooltip("Apply suspension force at the contact patch (like friction), not the wheel center. Stops bottom-out launches at speed.")]
public bool applySuspensionAtContactPoint
Field Value
| Type | Description |
|---|---|
| bool |
arbDamping
Anti-roll bar damping coefficient in Nm*s/rad. Prevents oscillation in ARB response. Typical: 5-20% of stiffness value.
Declaration
[Range(0, 2000)]
[Tooltip("ARB damping in Nm*s/rad. Typical: 5-20% of stiffness.")]
public float arbDamping
Field Value
| Type | Description |
|---|---|
| float |
arbStiffness
Anti-roll bar torsional stiffness in Nm/rad. Controls resistance to body roll when paired with opposite wheel. Wheels are auto-paired by position (similar Z, opposite X). Set to 0 to disable ARB for this wheel. Higher values reduce roll but increase load transfer. Typical: 500-5000 for road cars, 10000+ for race vehicles.
Declaration
[Range(0, 20000)]
[Tooltip("ARB stiffness in Nm/rad. 0 disables. Typical: 500-5000 for road cars.")]
public float arbStiffness
Field Value
| Type | Description |
|---|---|
| float |
autoCalculateLoadRating
When true, loadRating is automatically calculated based on vehicle mass and wheel count. Calculation: (vehicleMass * gravity / wheelCount) * 2
Declaration
[SerializeField]
[Tooltip("Automatically calculate load rating from vehicle mass. Disable to set manually.")]
public bool autoCalculateLoadRating
Field Value
| Type | Description |
|---|---|
| bool |
autoCalculateLoadSmoothingFactor
When true, loadSmoothingFactor is automatically calculated based on CoM height. Higher CoM results in lower smoothing factor for better stability.
Declaration
[SerializeField]
[Tooltip("Automatically calculate load smoothing factor from CoM height. Disable to set manually.")]
public bool autoCalculateLoadSmoothingFactor
Field Value
| Type | Description |
|---|---|
| bool |
axleLoadTransfer
Vertical load (N) transferred to this wheel by axle coupling - ARB force plus geometric roll-center transfer. Written by WheelControllerGroup.CalculateARB each substep, consumed by TickSuspension the following substep.
Declaration
[NonSerialized]
public float axleLoadTransfer
Field Value
| Type | Description |
|---|---|
| float |
brakeTorque
Brake torque applied to the wheel in Newton-meters [Nm]. Must be positive. This value directly opposes wheel rotation and brings the vehicle to a stop. Higher values provide stronger braking force but may cause wheel lock-up if excessive. Typical values range from 500-3000 Nm for passenger cars.
Declaration
[ShowInTelemetry(0, 1000, "0", "Nm", 1)]
[NonSerialized]
[Tooltip("Brake torque applied to the wheel in Newton-meters. Must be positive. Higher values provide stronger braking.")]
public float brakeTorque
Field Value
| Type | Description |
|---|---|
| float |
bumpStop
Bump stop configuration providing additional forces at suspension travel limits. Prevents harsh impacts when suspension bottoms out or over-extends.
Declaration
[SerializeField]
[Tooltip("Bump stop settings for suspension travel limits (compression and extension).")]
public BumpStop bumpStop
Field Value
| Type | Description |
|---|---|
| BumpStop |
camber
Current camber angle in degrees. Negative values tilt the top of the wheel towards the vehicle. Camber affects tire contact patch and cornering characteristics. Typical values: 0 to -3 degrees for road vehicles, -5 to -10 for race cars. Use camberCurve for dynamic camber that changes with suspension compression.
Declaration
[SerializeField]
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[Tooltip("Current camber angle in degrees. Negative tilts top of wheel inward. Affects cornering grip.")]
public float camber
Field Value
| Type | Description |
|---|---|
| float |
camberCurve
Curve representing spring compression on X-axis and camber angle on Y-axis.
Declaration
[Tooltip("Curve representing spring compression on X-axis and camber angle on Y-axis.")]
public AnimationCurve camberCurve
Field Value
| Type | Description |
|---|---|
| AnimationCurve |
castDirection
Wheel cast direction
Declaration
[NonSerialized]
[Tooltip("Wheel cast direction")]
public Vector3 castDirection
Field Value
| Type | Description |
|---|---|
| Vector3 |
castOrigin
Wheel cast origin
Declaration
[NonSerialized]
[Tooltip("Wheel cast origin")]
public Vector3 castOrigin
Field Value
| Type | Description |
|---|---|
| Vector3 |
counterTorque
The amount of torque returned by the wheel to the powertrain. Under no-slip conditions, this equals the input torque. During wheelspin or when airborne, the value will be less than the input torque, representing the torque that couldn't be transferred to the ground. Used by the powertrain solver to calculate engine load.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[Tooltip(" The amount of torque returned by the wheel.\r\n Under perfect grip conditions this will be equal to the torque that was put down.\r\n While in air the value will be equal to the source torque minus torque that is result of dW of the wheel.")]
[NonSerialized]
public float counterTorque
Field Value
| Type | Description |
|---|---|
| float |
damage
Current damage in range of [0,1] of this wheel
Declaration
[NonSerialized]
[Tooltip("Current damage in range of [0,1] of this wheel")]
public float damage
Field Value
| Type | Description |
|---|---|
| float |
damageCamberDrift
Maximum camber drift in degrees at full damage. Simulates bent wheel/suspension.
Declaration
[Range(0, 10)]
[Tooltip("Maximum camber drift in degrees at full damage. Simulates bent wheel/suspension.")]
public float damageCamberDrift
Field Value
| Type | Description |
|---|---|
| float |
damageGripReduction
Maximum grip reduction at full damage (0-1). 0.5 = 50% grip loss when damage=1.
Declaration
[Range(0, 1)]
[Tooltip("Maximum grip reduction at full damage (0-1). 0.5 = 50% grip loss at damage=1.")]
public float damageGripReduction
Field Value
| Type | Description |
|---|---|
| float |
damageMaxWobbleAngle
The amount of wobble around the X-axis the wheel will have when fully damaged. Part of the damage visualization. It does not affect handling.
Declaration
[Range(0, 90)]
[Tooltip("The amount of wobble around the X-axis the wheel will have when fully damaged.\r\nPart of the damage visualization and does not affect handling.")]
public float damageMaxWobbleAngle
Field Value
| Type | Description |
|---|---|
| float |
damageRollingResistanceMultiplier
Rolling resistance multiplier at full damage. 3 = 3x rolling resistance at damage=1.
Declaration
[Range(1, 5)]
[Tooltip("Rolling resistance multiplier at full damage. 3 = 3x rolling resistance when damage=1.")]
public float damageRollingResistanceMultiplier
Field Value
| Type | Description |
|---|---|
| float |
damper
Suspension damper configuration controlling bump and rebound behavior. Damper forces resist suspension movement to prevent oscillation. Bump rate controls compression damping (hitting bumps). Rebound rate controls extension damping (suspension returning to rest). Typical values: 5-20% of spring max force.
Declaration
[SerializeField]
[Tooltip("Suspension damper settings. Controls bump (compression) and rebound (extension) damping.")]
public Damper damper
Field Value
| Type | Description |
|---|---|
| Damper |
disableMotionVectors
Disables the motion vectors on the wheel visual to prevent artifacts due to the wheel rotation when using PostProcessing.
Declaration
[Tooltip("Disables the motion vectors on the wheel visual to prevent artefacts due to \r\nthe wheel rotation when using PostProcessing.")]
public bool disableMotionVectors
Field Value
| Type | Description |
|---|---|
| bool |
forward
Cached forward vector
Declaration
[NonSerialized]
[Tooltip("Cached forward vector")]
public Vector3 forward
Field Value
| Type | Description |
|---|---|
| Vector3 |
friction
Declaration
[NonSerialized]
public FrictionBase friction
Field Value
| Type | Description |
|---|---|
| FrictionBase |
frictionForce
Friction force vector
Declaration
[NonSerialized]
[Tooltip("Friction force vector")]
public Vector3 frictionForce
Field Value
| Type | Description |
|---|---|
| Vector3 |
frictionForceMagnitude
Current force in friction direction.
Declaration
[ShowInTelemetry(0, 10000, "0", "N", 1)]
[Tooltip("Current force in friction direction.")]
public Vector2 frictionForceMagnitude
Field Value
| Type | Description |
|---|---|
| Vector2 |
frictionSlip
Current slip in friction direction.
Declaration
[ShowInTelemetry(0, 1, "0.00", null, 1)]
[Tooltip("Current slip in friction direction.")]
public Vector2 frictionSlip
Field Value
| Type | Description |
|---|---|
| Vector2 |
frictionSpeed
Speed at the point of contact with the surface.
Declaration
[ShowInTelemetry(0, 10, "0.0", "m/s", 1)]
[Tooltip("Speed at the point of contact with the surface.")]
public Vector2 frictionSpeed
Field Value
| Type | Description |
|---|---|
| Vector2 |
hitRigidbodyForce
Force applied to the hit Rigidbody if any is hit.
Declaration
[NonSerialized]
[Tooltip("Force applied to the hit Rigidbody if any is hit.")]
public Vector3 hitRigidbodyForce
Field Value
| Type | Description |
|---|---|
| Vector3 |
hitRigidbodyForcePosition
Point on the hit Rigidbody that the wheel is in contact with.
Declaration
[NonSerialized]
[Tooltip("Point on the hit Rigidbody that the wheel is in contact with.")]
public Vector3 hitRigidbodyForcePosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
implicitDamping
Applies implicit damper integration to prevent oscillation at low physics rates. When enabled, damper forces are scaled to prevent numerical overshoot. Recommended: Always on unless debugging specific damper behavior.
Declaration
[Tooltip("Enable implicit damping to prevent jitter at low physics rates (40-50Hz).")]
public bool implicitDamping
Field Value
| Type | Description |
|---|---|
| bool |
initialized
True when the WheelController has been initialized and is ready for simulation. Set to true after Initialize() completes successfully. The wheel will not update physics until this is true.
Declaration
[NonSerialized]
public bool initialized
Field Value
| Type | Description |
|---|---|
| bool |
isGrounded
Indicates whether the wheel is currently in contact with the ground. When true, friction and suspension forces are calculated and applied. When false (airborne), only gravity and wheel inertia affect rotation. Used for determining when to play skid sounds, particle effects, etc.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[NonSerialized]
[Tooltip("True when wheel is touching ground. False when airborne.")]
public bool isGrounded
Field Value
| Type | Description |
|---|---|
| bool |
isSkiddingLaterally
Is the wheel skidding laterally (sideways)?
Declaration
[Tooltip("Is the wheel skidding laterally (sideways)?")]
public bool isSkiddingLaterally
Field Value
| Type | Description |
|---|---|
| bool |
isSkiddingLongitudinally
Is the wheel skidding longitudinally (forward)?
Declaration
[Tooltip("Is the wheel skidding longitudinally (forward)?")]
public bool isSkiddingLongitudinally
Field Value
| Type | Description |
|---|---|
| bool |
lastStepFrame
Frame on which the last step happened
Declaration
[Tooltip("Frame on which the last step happened")]
public int lastStepFrame
Field Value
| Type | Description |
|---|---|
| int |
lastSubstep
Substep index on which the last substep happened
Declaration
[NonSerialized]
public int lastSubstep
Field Value
| Type | Description |
|---|---|
| int |
lastSubstepFrame
Physics frame on which the last substep occurred
Declaration
[NonSerialized]
public int lastSubstepFrame
Field Value
| Type | Description |
|---|---|
| int |
layerMask
Layer mask determining which collision layers the wheel will detect during ground casting. Typically includes ground/terrain layers while excluding the vehicle itself. Default is layer 0 (Default layer). Adjust to exclude water, triggers, or other non-solid layers.
Declaration
[Tooltip("Layers that will be detected by wheel ground casting. Exclude vehicle and trigger layers.")]
public LayerMask layerMask
Field Value
| Type | Description |
|---|---|
| LayerMask |
load
Current tire load in Newtons [N]. Represents the vertical force on the tire. Calculated from spring force plus damper force when grounded. Affects available friction - higher load generally provides more grip up to the tire's limit. Compare with loadRating to determine if tire is overloaded.
Declaration
[Tooltip("Current tire load in Newtons. Higher load provides more grip up to tire limits.")]
[ShowInTelemetry(0, 10000, "0", "N", 1)]
[NonSerialized]
public float load
Field Value
| Type | Description |
|---|---|
| float |
loadRating
Maximum load the tire is rated for in Newtons [N]. Used to calculate friction coefficients. Should be approximately 1.5-2x the static load on the wheel for optimal behavior. Too low: Vehicle will slide excessively. Too high: Friction calculations become unrealistic. Typical values: 3000-6000 N for passenger cars, 10000-20000 N for trucks. Can be calculated from tire load index or set to 2x the resting spring force.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[SerializeField]
[Tooltip("Maximum load the tire is rated for in [N]. Used to calculate friction. The default value is adequate for most cars\r\nexcept for larger and heavier vehicles such as semi-trucks. A good rule of the thumb is that this\r\nvalue should be 1.5x the Load (Debug tab) while the vehicle is stationary.")]
public float loadRating
Field Value
| Type | Description |
|---|---|
| float |
loadSmoothingFactor
Load smoothing factor (0-1). Higher values = more responsive but potentially unstable. Lower values = smoother but may cause friction phase lag. Default 0.6 works for most vehicles. High CoM vehicles benefit from 0.4-0.5. When autoCalculateLoadSmoothingFactor is enabled, this is set automatically based on CoM height.
Declaration
[SerializeField]
[Range(0.3, 0.9)]
[Tooltip("Load smoothing factor. Lower = smoother (high CoM), Higher = responsive (low CoM).")]
public float loadSmoothingFactor
Field Value
| Type | Description |
|---|---|
| float |
localAxleRotation
Local rotation of the wheel around the wheel axle.
Declaration
[NonSerialized]
public Quaternion localAxleRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
localCamberRotation
Local rotation of the wheel around the camber (forward) axis.
Declaration
[NonSerialized]
public Quaternion localCamberRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
localForward
Suspension forward direction vector in vehicle local space with steering applied. Updated each physics step after applying steer rotation to the suspension.
Declaration
[NonSerialized]
public Vector3 localForward
Field Value
| Type | Description |
|---|---|
| Vector3 |
localMatrix
Initial suspension matrix without steer rotation, relative to the vehicle. Chain: [LOCAL] - transforms from wheel mount local space to vehicle space (no steer). Contains initial position and orientation from camber/toe/caster setup.
Declaration
[NonSerialized]
public Matrix4x4 localMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
localMatrixWithRotation
Suspension matrix with steer rotation applied, relative to the vehicle. Chain: [STEER] * [LOCAL] - localMatrix rotated by steerAngle around localUp. Used for suspension world position and orientation calculations.
Declaration
[NonSerialized]
public Matrix4x4 localMatrixWithRotation
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
localPosition
Relative position of the wheel.
Declaration
[NonSerialized]
public Vector3 localPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
localRight
Suspension right direction vector in vehicle local space with steering applied. Points along the wheel axle direction. Updated each physics step.
Declaration
[NonSerialized]
public Vector3 localRight
Field Value
| Type | Description |
|---|---|
| Vector3 |
localRotation
Suspension rotation quaternion in vehicle local space with steering applied. Represents the orientation of the suspension after steer angle is applied.
Declaration
[NonSerialized]
public Quaternion localRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
localToWorldMatrix
Transformation matrix from suspension local space to world space. Chain: [VEHICLE] * [STEER] * [LOCAL] = vehicleLocalToWorldMatrix * localMatrixWithRotation. IMPORTANT: This already includes steering rotation. Do NOT multiply with localMatrixWithRotation again or steering will be applied twice!
Declaration
[NonSerialized]
public Matrix4x4 localToWorldMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
localTreadPosition
Position of the tire contact point (bottom of the wheel) in vehicle local space. Calculated as wheel position minus wheel radius in the up direction.
Declaration
[NonSerialized]
public Vector3 localTreadPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
localUp
Suspension up direction vector in vehicle local space (without steering applied). Points along the suspension travel direction. Remains constant relative to vehicle.
Declaration
[NonSerialized]
public Vector3 localUp
Field Value
| Type | Description |
|---|---|
| Vector3 |
localWobbleRotation
Local rotation quaternion for damage wobble effect applied to the wheel visual. Rotates around the wheel up axis based on damage value and axle rotation. Used purely for visual damage effect and does not affect physics.
Declaration
[NonSerialized]
public Quaternion localWobbleRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
maxSuspensionForceScale
Caps total suspension force at this multiple of the spring's configured force capacity (maxForce plus the configured bump-stop force). Clips the peak spring+damper+bump-stop force on a hard bottom-out so the unclamped force can't spike into the chassis. Bounds the peak, not the integrated landing impulse - moment-arm removal (applySuspensionAtContactPoint) does the main anti-pitch work. Inert in normal driving and aggressive jump landings; only bites on bottom-out impacts. Raise it for stiff custom dampers run with the compression bump stop disabled. Zero or less disables the cap.
Declaration
[Tooltip("Cap on suspension force as a multiple of spring capacity. Clips the bottom-out force peak. 0 disables.")]
public float maxSuspensionForceScale
Field Value
| Type | Description |
|---|---|
| float |
meshColliderLayer
Layer the mesh collider of the wheel is on.
Declaration
[Tooltip("Layer the mesh collider of the wheel is on.")]
public int meshColliderLayer
Field Value
| Type | Description |
|---|---|
| int |
motorTorque
Motor torque applied to the wheel in Newton-meters [Nm]. Can be positive (acceleration) or negative (engine braking). In NWH Vehicle Physics 2, this value is readonly and calculated by the powertrain solver. Do not set directly - use the vehicle's powertrain components instead.
Declaration
[ShowInTelemetry(0, 1000, "0", "Nm", 1)]
[Tooltip("Motor torque applied to the wheel. Since NWH Vehicle Physics 2 the value is readonly and setting it will have no effect\r\nsince torque calculation is done inside powertrain solver.")]
[NonSerialized]
public float motorTorque
Field Value
| Type | Description |
|---|---|
| float |
normalizedSlip
Slip normalized to [-1, 1] X = longitudinal/forward Y = lateral/sideways
Declaration
[NonSerialized]
[Tooltip("Slip normalized to [-1, 1] X = longitudinal/forward Y = lateral/sideways")]
public Vector2 normalizedSlip
Field Value
| Type | Description |
|---|---|
| Vector2 |
otherBodyForceScale
Scales forces applied to other Rigidbodies that the wheel contacts. Values below 1.0 reduce forces to prevent lightweight objects from being launched. Set to 0 to disable forces on other bodies entirely. Useful for preventing physics instability when driving over small props. Typical values: 0.1-0.5 for arcade games, 0.5-1.0 for simulations.
Declaration
[Tooltip("Scales the forces applied to other Rigidbodies. Useful for interacting\r\nwith lightweight objects and prevents them from flying away or glitching out.")]
public float otherBodyForceScale
Field Value
| Type | Description |
|---|---|
| float |
right
Suspension right direction vector in world space with steering applied. Points along the wheel axle direction. Updated every physics step.
Declaration
[NonSerialized]
public Vector3 right
Field Value
| Type | Description |
|---|---|
| Vector3 |
rigidbodyGroup
Reference to the rigidbody group this wheel belongs to for substepping
Declaration
[NonSerialized]
public WheelControllerGroup rigidbodyGroup
Field Value
| Type | Description |
|---|---|
| WheelControllerGroup |
rollCenterHeight
Suspension roll center height in meters above the contact patch. Lateral friction force is applied to the body at this height and the geometric share of lateral load transfer (Fy * h / track) reaches the wheel loads instantly instead of waiting for body roll. 0 keeps legacy behavior. Typical: 0.03-0.12 front, 0.08-0.25 rear.
Declaration
[Range(0, 0.5)]
[Tooltip("Roll center height (m) above the contact patch. 0 = legacy behavior. Typical: 0.03-0.12 front, 0.08-0.25 rear.")]
public float rollCenterHeight
Field Value
| Type | Description |
|---|---|
| float |
rollingResistanceTorque
Constant resistance torque in [Nm] that opposes wheel rotation, simulating rolling resistance. Applied continuously like a light brake to simulate tire deformation and bearing friction. Higher values make the vehicle slow down faster when coasting. Typical values: 10-30 Nm for cars, 50-200 Nm for trucks. Set to 0 for frictionless rolling (unrealistic but useful for testing).
Declaration
[Range(0, 500)]
[Tooltip("Rolling resistance torque in Nm. Higher values increase coasting deceleration.")]
public float rollingResistanceTorque
Field Value
| Type | Description |
|---|---|
| float |
seedCompressionVelocityFromContact
On the first substep a wheel re-contacts ground after being airborne, take the compression velocity from the wheel's physical closing speed instead of the geometric length jump, which on a hard landing is a teleport-into-travel artifact. Avoids a spurious damper spike on landing.
Declaration
[Tooltip("Seed first-contact compression velocity from real closing speed, not the geometric length jump.")]
public bool seedCompressionVelocityFromContact
Field Value
| Type | Description |
|---|---|
| bool |
showGizmos
Enable to show debug gizmos in the scene view when the wheel is selected. Includes suspension visualization, contact points, friction vectors, and wheel geometry.
Declaration
[Tooltip("Show debug gizmos in scene view (suspension, contact points, friction vectors).")]
public bool showGizmos
Field Value
| Type | Description |
|---|---|
| bool |
spring
Suspension spring configuration controlling vertical wheel movement. Max Force: Maximum force at full compression (should support ~3x static wheel load). Max Length: Total suspension travel in meters (typically 0.1-0.3m for cars). Force Curve: Allows progressive or digressive spring rates. Spring should rest at ~30% compression under static load for optimal behavior.
Declaration
[SerializeField]
public Spring spring
Field Value
| Type | Description |
|---|---|
| Spring |
stabilityControl
Per-wheel ABS and TCS settings. Can be coordinated by vehicle-level modules.
Declaration
[SerializeField]
[Tooltip("Per-wheel ABS and TCS settings. Can be coordinated by vehicle-level modules.")]
public WheelController.StabilityControlSettings stabilityControl
Field Value
| Type | Description |
|---|---|
| WheelController.StabilityControlSettings |
steerAngle
Current steering angle of the wheel in degrees. Positive values steer right, negative values steer left. Typically limited to ±30-45 degrees for front wheels. Can be negative for rear-wheel steering (improves turning radius). Applied around the local up axis of the suspension.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[NonSerialized]
[Tooltip("Current steer angle of the wheel, in deg.")]
public float steerAngle
Field Value
| Type | Description |
|---|---|
| float |
steerRotationMatrix
Rotation matrix representing the steering angle transformation in vehicle local space. Rotates the suspension around its up axis by the steer angle. Updated each physics step.
Declaration
[NonSerialized]
public Matrix4x4 steerRotationMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
steppedThisSubstep
True if wheel was already stepped during current substep (prevents double-stepping by powertrain)
Declaration
[NonSerialized]
public bool steppedThisSubstep
Field Value
| Type | Description |
|---|---|
| bool |
suspensionForce
Total suspension force vector applied to the vehicle from spring and damper. Calculated as (spring force + damper force) * hit normal when grounded. Zero when airborne.
Declaration
[NonSerialized]
public Vector3 suspensionForce
Field Value
| Type | Description |
|---|---|
| Vector3 |
targetRigidbody
The parent Rigidbody that receives all forces from this wheel. Must be the vehicle's main Rigidbody. Automatically found if not set. All suspension, friction, and torque forces are applied to this body. The WheelController must be a child of this Rigidbody's GameObject.
Declaration
[SerializeField]
[Tooltip("The Rigidbody to which the forces will be applied.")]
public Rigidbody targetRigidbody
Field Value
| Type | Description |
|---|---|
| Rigidbody |
tcsActive
True when TCS is actively applying counter-torque this frame.
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
[NonSerialized]
[Tooltip("True when TCS is actively applying counter-torque.")]
public bool tcsActive
Field Value
| Type | Description |
|---|---|
| bool |
tcsCounterTorque
Counter-torque applied by TCS this frame (Nm). For telemetry/debugging.
Declaration
[ShowInTelemetry(0, 3000, "0", "Nm", 1)]
[NonSerialized]
[Tooltip("Counter-torque applied by TCS this frame in Nm.")]
public float tcsCounterTorque
Field Value
| Type | Description |
|---|---|
| float |
tireScrub
Tire scrub intensity (0-1) for FFB vibration effect. Indicates how much the tire is sliding/scrubbing beyond grip threshold.
Declaration
[ShowInTelemetry(0, 1, "0.00", null, 1)]
[NonSerialized]
[Tooltip("Tire scrub intensity for FFB. 0 = gripping, 1 = fully sliding.")]
public float tireScrub
Field Value
| Type | Description |
|---|---|
| float |
treadPosition
Position of the tire contact point (bottom of the wheel) in world space. Calculated as wheel position minus wheel radius in the wheel up direction. Used for friction force calculations and determining contact point.
Declaration
[NonSerialized]
public Vector3 treadPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
up
Suspension up direction vector in world space with steering applied. Points along the suspension travel direction. Updated every physics step.
Declaration
[NonSerialized]
public Vector3 up
Field Value
| Type | Description |
|---|---|
| Vector3 |
useCamberCurve
If true, the camber curve will be used to calculate camber based on suspension compression. If false, camber can be set manually or by external systems (e.g., solid axle in VehiclePhysics2).
Declaration
[Tooltip("Enable to use camber curve. Disable if using external camber control (e.g., solid axle).")]
public bool useCamberCurve
Field Value
| Type | Description |
|---|---|
| bool |
useContactModification
Experimental feature using Unity's contact modification API to reduce impact forces. Softens collisions in the wheel's forward direction to prevent harsh impacts when hitting curbs or obstacles. Helps vehicles drive over small obstacles more smoothly. May cause wheels to clip through thin objects if not configured properly.
Declaration
[Tooltip("Experimental! Uses contacts modification API to soften or ignore collisions in the wheel forward direction.")]
public bool useContactModification
Field Value
| Type | Description |
|---|---|
| bool |
vehicleColliders
Vehicle colliders for cast filtering. Updated each time Initialize() is called. Add colliders manually or call Initialize() after adding or removing colliders from the vehicle.
Declaration
[Tooltip("Vehicle colliders for cast filtering. Updated each time Initialize() is called. Add colliders manually\r\nor call Initialize() after adding or removing colliders from the vehicle.")]
public HashSet<Collider> vehicleColliders
Field Value
| Type | Description |
|---|---|
| HashSet<Collider> |
vehicleLocalToWorldMatrix
Transformation matrix from vehicle local space to world space. Cached from the parent Rigidbody transform each physics step for performance.
Declaration
[NonSerialized]
public Matrix4x4 vehicleLocalToWorldMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
vehicleTransform
Reference to the vehicle's root Transform (parent Rigidbody's transform). The WheelController must be a direct child of this transform. Cached during initialization for performance.
Declaration
[NonSerialized]
public Transform vehicleTransform
Field Value
| Type | Description |
|---|---|
| Transform |
vehicleWorldToLocalMatrix
Transformation matrix from world space to vehicle local space. Inverse of vehicleLocalToWorldMatrix. Updated each physics step.
Declaration
[NonSerialized]
public Matrix4x4 vehicleWorldToLocalMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
wheel
Wheel configuration containing physical properties and visual references. Radius: Wheel radius in meters (typically 0.3-0.5m for cars). Width: Wheel width in meters (typically 0.15-0.3m for cars). Mass: Affects rotational inertia only, not vehicle weight. Visual containers: References to rotating (wheel mesh) and non-rotating (brake caliper) parts.
Declaration
[Tooltip("Wheel physical properties and visual references.")]
[SerializeField]
public Wheel wheel
Field Value
| Type | Description |
|---|---|
| Wheel |
wheelForward
Wheel's forward direction vector in world space after suspension compression and steering. Points in the rolling direction of the wheel. Updated each physics step.
Declaration
[NonSerialized]
public Vector3 wheelForward
Field Value
| Type | Description |
|---|---|
| Vector3 |
wheelHit
Contains detailed information about the current ground contact point. Only valid when isGrounded is true. Includes hit point, normal, collider, and surface friction properties. Used for surface-specific effects and sounds. Updated every physics frame during ground detection.
Declaration
[NonSerialized]
[Tooltip("Contains data about the ground contact point. Not valid if !_isGrounded.")]
public WheelHit wheelHit
Field Value
| Type | Description |
|---|---|
| WheelHit |
wheelLocalMatrix
Wheel's transformation matrix for positioning only (identity rotation + spring offset). Chain: [IDENTITY rotation] + position offset from spring length and scrub radius. IMPORTANT: Rotation is identity because steering is already in localToWorldMatrix. wheelWorldMatrix = localToWorldMatrix * wheelLocalMatrix applies steer exactly once.
Declaration
[NonSerialized]
public Matrix4x4 wheelLocalMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
wheelLocalPosition
Wheel's position in vehicle local space after suspension compression is applied. Y component changes with suspension travel. Used for visual positioning.
Declaration
[NonSerialized]
public Vector3 wheelLocalPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
wheelLocalRotation
Wheel's rotation quaternion in vehicle local space with steering applied. Extracted from wheelLocalMatrix each physics step.
Declaration
[NonSerialized]
public Quaternion wheelLocalRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
wheelRight
Wheel's right direction vector in world space after suspension compression and steering. Points along the wheel axle. Updated each physics step.
Declaration
[NonSerialized]
public Vector3 wheelRight
Field Value
| Type | Description |
|---|---|
| Vector3 |
wheelUp
Wheel's up direction vector in world space after suspension compression and steering. Points perpendicular to the wheel's rolling plane. Updated each physics step.
Declaration
[NonSerialized]
public Vector3 wheelUp
Field Value
| Type | Description |
|---|---|
| Vector3 |
wheelWorldMatrix
Wheel's transformation matrix in world space including suspension compression. Chain: [VEHICLE] * [STEER] * [LOCAL] = localToWorldMatrix * wheelLocalMatrix. Since wheelLocalMatrix has identity rotation, this equals localToWorldMatrix with position offset for spring compression and scrub radius. wheelForward, wheelRight, wheelUp are extracted from this matrix.
Declaration
[NonSerialized]
public Matrix4x4 wheelWorldMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
wheelWorldPosition
Wheel's position in world space after suspension compression is applied. The actual location of the wheel center accounting for spring travel.
Declaration
[NonSerialized]
public Vector3 wheelWorldPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
wheelWorldRotation
Wheel's rotation quaternion in world space with steering applied. Extracted from wheelWorldMatrix each physics step.
Declaration
[NonSerialized]
public Quaternion wheelWorldRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
worldMatrix
Suspension transformation matrix in world space with steering rotation applied. Combines vehicle transform, suspension local matrix, and steering rotation.
Declaration
[NonSerialized]
public Matrix4x4 worldMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
worldPosition
Suspension origin position in world space (not the wheel position). The suspension pivot point from which the wheel travels up and down.
Declaration
[NonSerialized]
public Vector3 worldPosition
Field Value
| Type | Description |
|---|---|
| Vector3 |
worldRotation
Suspension rotation quaternion in world space with steering applied. Extracted from worldMatrix each physics step.
Declaration
[NonSerialized]
public Quaternion worldRotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
worldToLocalMatrix
Transformation matrix from world space to suspension local space. Inverse of localToWorldMatrix. Used for coordinate conversions.
Declaration
[NonSerialized]
public Matrix4x4 worldToLocalMatrix
Field Value
| Type | Description |
|---|---|
| Matrix4x4 |
Properties
| Edit this page View SourceDamageGripMultiplier
Gets the grip multiplier based on current damage. Used by friction calculations.
Declaration
public float DamageGripMultiplier { get; }
Property Value
| Type | Description |
|---|---|
| float |
EffectiveRollingResistanceTorque
Gets the effective rolling resistance including damage effects.
Declaration
public float EffectiveRollingResistanceTorque { get; }
Property Value
| Type | Description |
|---|---|
| float |
IsStaticFriction
True when wheel is in static friction mode (anchored).
Declaration
[ShowInTelemetry(NaN, NaN, null, null, 1)]
public bool IsStaticFriction { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Methods
| Edit this page View SourceFindOrSpawnVisualContainers()
Locates or creates the required child containers for wheel visuals. Creates two containers:
- "Rotating": For the wheel mesh and any parts that spin with the wheel
- "NonRotating": For brake calipers, suspension arms, or other static parts Automatically called during initialization but can be called manually if needed.
Declaration
public void FindOrSpawnVisualContainers()
Initialize()
Initializes or reinitializes the WheelController after configuration changes. Must be called after:
- Changing wheel radius, width, or mass
- Moving or rotating the WheelController transform
- Changing the parent Rigidbody
- Adding or removing vehicle colliders Automatically called on Start() but can be called manually when making runtime changes.
Declaration
public void Initialize()
PositionToVisual()
Automatically positions the WheelController transform above the wheel visual. Calculates the appropriate suspension origin position based on:
- Current spring settings and expected compression under load
- Vehicle mass and estimated static load distribution
- Visual mesh position Useful during initial setup to quickly position suspension points. The wheel visual should be at its desired rest position before calling.
Declaration
public void PositionToVisual()
SetRuntimeDefaultsIfNeeded(bool, bool)
Sets default values for wheel configuration if not already set. Automatically called when component is added or reset. Configures spring, damper, and friction values based on vehicle mass.
Declaration
public void SetRuntimeDefaultsIfNeeded(bool reset = false, bool findWheelVisuals = true)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | reset | Force reset all values even if already configured |
| bool | findWheelVisuals | Attempt to automatically locate wheel mesh GameObjects |
SubStep(float, WheelControllerState, WheelControllerGroup)
Execute a single physics substep using cached rigidbody state. Called by WheelControllerManager during substepping.
Declaration
public void SubStep(float substepDt, WheelControllerState rbState, WheelControllerGroup group)
Parameters
| Type | Name | Description |
|---|---|---|
| float | substepDt | Substep delta time |
| WheelControllerState | rbState | Cached rigidbody state |
| WheelControllerGroup | group | Rigidbody group for force accumulation |