NWH Vehicle Physics 2
Search Results for

    Show / Hide Table of Contents

    Architecture Overview

    NWH Vehicle Physics 2 uses a modular component-based architecture with VehicleController as the central hub coordinating all vehicle systems.


    Component Hierarchy

    VehicleController is the central hub that coordinates all vehicle systems:

    VehicleController (Main Hub)
    ├── Powertrain
    │   ├── EngineComponent (power generation)
    │   ├── ClutchComponent (power transfer control)
    │   ├── TransmissionComponent (gear ratios)
    │   ├── DifferentialComponent(s) (torque distribution)
    │   └── WheelComponent(s) (power sinks → WheelController)
    ├── Steering (angle calculations, speed-dependent reduction)
    ├── Brakes (torque application, brake distribution)
    ├── Input
    │   └── VehicleInputHandler
    │       ├── InputSystemVehicleInputProvider
    │       ├── InputManagerVehicleInputProvider
    │       └── MobileVehicleInputProvider
    ├── EffectManager
    │   ├── LightsManager (headlights, brake, indicators)
    │   ├── SkidmarkManager (tire marks)
    │   ├── SurfaceParticleManager (dust, dirt, spray)
    │   └── Exhausts (smoke, flash)
    ├── SoundManager
    │   ├── EngineRunningComponent
    │   ├── EngineStartStopComponent
    │   ├── TransmissionWhineComponent
    │   ├── WheelSkidComponent
    │   ├── WheelTireNoiseComponent
    │   └── [other sound components]
    ├── GroundDetection (surface type identification)
    ├── DamageHandler (collision damage)
    └── ModuleManager
        ├── ABSModule
        ├── TCSModule
        ├── ESCModule
        ├── CruiseControlModule
        ├── ArcadeModule
        ├── MotorcycleModule
        ├── TrailerModule / TrailerHitchModule
        ├── AerodynamicsModule
        ├── NOSModule
        └── [15+ optional modules]
    

    VehicleComponent Lifecycle

    All vehicle systems inherit from VehicleComponent, providing a standardized lifecycle. Methods are prefixed VC_ to avoid conflicts with Unity callbacks.

    Lifecycle Stages

                        ┌─────────────────────────────────────┐
                        │         INITIALIZATION              │
                        └─────────────────────────────────────┘
                                        │
                        VC_Initialize(VehicleController vc)
                               Sets parent reference
                                        │
                               VC_Initialize()
                          Component-specific setup
                                        │
                         VC_LoadStateFromStateSettings()
                        Apply LOD-based initial state
                                        │
                        ┌─────────────────────────────────────┐
                        │          RUNTIME LOOP               │
                        └─────────────────────────────────────┘
                                        │
                        ┌───────────────┴───────────────┐
                        │                               │
                  VC_Enable()                    VC_Disable()
               Component active              Component inactive
                        │                               │
                        ├───────────────────────────────┤
                        │                               │
              VC_FixedUpdate(dt)                       │
               Physics updates                         │
                        │                               │
               VC_Update(dt)                           │
               Visual updates                          │
                        │                               │
                        └───────────────────────────────┘
    

    Lifecycle Methods

    Method When Called Purpose
    VC_Initialize(vc) Once on startup Sets VehicleController reference
    VC_Initialize() Once on startup Component-specific initialization
    VC_SetDefaults() On first setup Apply default configuration values
    VC_Validate() Editor/runtime Validate component configuration
    VC_LoadStateFromStateSettings() On state change Apply LOD-based state
    VC_Enable() When enabled Activate component
    VC_Disable() When disabled Deactivate component
    VC_FixedUpdate(dt) Each FixedUpdate Physics calculations
    VC_Update(dt) Each Update Visual/audio updates

    Example Implementation

    public class CustomComponent : VehicleComponent
    {
        public override void VC_Initialize()
        {
            base.VC_Initialize();
            // Setup code here
        }
    
        public override void VC_Enable()
        {
            base.VC_Enable();
            // Called when component becomes active
        }
    
        public override void VC_FixedUpdate(float dt)
        {
            base.VC_FixedUpdate(dt);
            if (!IsActive) return;
    
            // Physics calculations here
        }
    
        public override void VC_Update(float dt)
        {
            base.VC_Update(dt);
            if (!IsActive) return;
    
            // Visual updates here
        }
    }
    

    Update Order

    Execution Order Configuration

    NWH Vehicle Physics uses Unity's Script Execution Order to ensure proper update sequencing:

    Order Component Responsibility
    90 VehicleController.FixedUpdate Input, steering, brakes, wheel groups
    100 WheelController.OnEnable Register with WheelControllerManager
    110 WheelControllerManager.FixedUpdate Substep loop with powertrain callbacks

    FixedUpdate Flow

    Each physics frame follows this sequence:

    VehicleController.FixedUpdate() [Order 90]
    ├── 1. Process input states
    ├── 2. Update steering angles
    ├── 3. Calculate brake torques
    ├── 4. Update wheel groups
    └── 5. Prepare for physics substep
    
    WheelControllerManager.FixedUpdate() [Order 110]
    ├── BeginFrame()
    │   └── Read Rigidbody state (position, velocity, inertia)
    │
    ├── SUBSTEP LOOP (N iterations, typically 4)
    │   ├── BeginSubstep()
    │   │   └── Reset force accumulators
    │   │
    │   ├── ISubstepCallback.OnBeforeSubstep(dt)
    │   │   └── Powertrain.IntegrateDownwards() ← Engine torque propagation
    │   │
    │   ├── WheelController.SubStep(dt)
    │   │   ├── Ground detection
    │   │   ├── Suspension forces
    │   │   ├── Friction forces
    │   │   └── Accumulate forces
    │   │
    │   ├── CoordinateStaticFrictionBreak()
    │   │
    │   └── EndSubstep()
    │       └── Apply forces to state, integrate
    │
    └── EndFrame()
        └── Write final velocity to Rigidbody
    

    Update Flow

    Each render frame follows this sequence:

    VehicleController.Update()
    ├── 1. LOD distance checks
    ├── 2. Update sound components
    ├── 3. Update visual effects
    └── 4. Update module visuals
    
    VehicleController.LateUpdate()
    └── 1. Camera and final visual updates
    

    Physics Substepping

    The powertrain and wheel physics run at a higher frequency than Unity's FixedUpdate through the substepping system.

    How Substepping Works

    Unity FixedUpdate (60Hz / 0.01667s)
    │
    └── WheelControllerManager
        ├── Substep 0 (0.00417s)
        │   ├── Powertrain calculates torques
        │   └── Wheel calculates forces
        │
        ├── Substep 1 (0.00417s)
        │   ├── Powertrain responds to wheel state
        │   └── Wheel recalculates with new torque
        │
        ├── Substep 2 (0.00417s)
        │   └── ...
        │
        └── Substep 3 (0.00417s)
            └── Final forces applied to Rigidbody
    

    Configuration

    The effective physics rate is calculated as:

    Effective Rate = (1 / fixedDeltaTime) * substepCount
    
    Example:
    - Fixed Timestep: 0.01667s (60Hz desktop, recommended)
    - Substeps: 4
    - Effective Rate: 60 * 4 = 240Hz
    

    See WheelControllerManager in the WheelController3D package documentation for detailed substepping documentation.


    State System (LOD)

    StateSettings provides distance-based component activation for performance optimization.

    LOD Levels

    Level Distance Description
    LOD 0 Close Full simulation, all effects/sounds
    LOD 1 Medium Reduced quality, simplified physics
    LOD 2 Far Minimal simulation, no effects
    LOD 3 Very Far Component sleeping, minimal overhead

    State Transitions

    Distance increases →
    ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
    │  LOD 0  │ → │  LOD 1  │ → │  LOD 2  │ → │  LOD 3  │
    │  Full   │    │ Reduced │    │ Minimal │    │  Sleep  │
    └─────────┘    └─────────┘    └─────────┘    └─────────┘
    ← Distance decreases
    

    Per-Component State

    Each VehicleComponent can define its behavior at each LOD level:

    // In StateSettings ScriptableObject
    public class ComponentState
    {
        public bool isEnabled;
        public int lodLevel;
        // Component-specific settings per LOD
    }
    

    See StateSettings and LOD for configuration details.


    Input System Architecture

    The input system uses a provider pattern for platform abstraction.

    Input Flow

    Hardware Input
          │
          ▼
    SceneInputProvider (scene-level)
    ├── InputSystemSceneInputProvider
    ├── InputManagerSceneInputProvider
    └── MobileSceneInputProvider
          │
          ▼
    VehicleInputHandler (per-vehicle)
          │
          ▼
    VehicleInputStates
    ├── throttle (0-1)
    ├── brakes (0-1)
    ├── steering (-1 to 1)
    ├── clutch (0-1)
    ├── handbrake (bool)
    ├── shiftUp (bool)
    ├── shiftDown (bool)
    └── [other inputs]
          │
          ▼
    Vehicle Systems
    ├── Powertrain (throttle, clutch, shifts)
    ├── Steering (steering)
    ├── Brakes (brakes, handbrake)
    └── Modules (horn, lights, etc.)
    

    Input Provider Types

    Provider Platform Input Source
    InputSystemSceneInputProvider Desktop/Console Unity Input System
    InputManagerSceneInputProvider Desktop Legacy Input Manager
    MobileSceneInputProvider Mobile Touch controls
    FFBInputProvider Desktop Force feedback wheels

    Module System

    Modules are optional vehicle features that can be added, removed, or configured independently.

    Module Categories

    Driver Assistance:

    • ABSModule - Anti-lock Braking System
    • TCSModule - Traction Control System
    • ESCModule - Electronic Stability Control
    • CruiseControlModule - Speed maintenance
    • SpeedLimiterModule - Maximum speed enforcement

    Vehicle Types:

    • MotorcycleModule - Lean physics
    • ArcadeModule - Simplified physics

    Features:

    • TrailerModule / TrailerHitchModule - Towing
    • AerodynamicsModule - Downforce
    • NOSModule - Nitrous boost
    • FuelModule - Fuel consumption
    • FlipOverModule - Auto-recovery
    • MetricsModule - Performance tracking
    • RiggingModule - Visual bone animation
    • AirSteerModule - In-air steering

    Module Lifecycle

    Modules follow the same VehicleComponent lifecycle but are managed through ModuleManager:

    // Enable/disable modules
    vc.moduleManager.SetModuleState("ABS", true);
    vc.moduleManager.SetModuleState("TCS", false);
    
    // Get module reference
    var absModule = vc.moduleManager.GetModule<ABSModule>();
    
    // Check module state
    bool isActive = absModule?.IsEnabled ?? false;
    

    Design Patterns Used

    Component Pattern

    All vehicle systems inherit from VehicleComponent for consistent lifecycle management.

    Provider Pattern

    Input system uses pluggable providers for platform abstraction.

    Manager Pattern

    Centralized managers coordinate related components:

    • ModuleManager - Optional modules
    • SoundManager - Audio playback
    • EffectManager - Visual effects
    • WheelControllerManager - Physics substepping

    Observer Pattern

    Event-based notifications for state changes:

    • onLODChanged - LOD level transitions
    • onVehicleChanged - Active vehicle switching
    • onActiveVehicleChanged - Global vehicle tracking

    State Pattern

    LOD system manages component states based on distance.


    Best Practices

    Initialization

    1. Use VC_Initialize() for setup, not Unity's Awake() or Start()
    2. Access other components only after initialization
    3. Use VC_SetDefaults() for default values, not field initializers

    Updates

    1. Physics calculations go in VC_FixedUpdate(dt)
    2. Visual updates go in VC_Update(dt)
    3. Always check if (!IsActive) return; at the start

    Performance

    1. Enable LOD system for multiple vehicles
    2. Disable unused modules
    3. Use appropriate substep count for platform
    4. Pool effects (skidmarks, particles)

    Debugging

    1. Enable gizmos to visualize wheel positions and forces
    2. Use Telemetry window (Window > NWH > Telemetry)
    3. Check Unity Profiler for bottlenecks
    4. Recommended Fixed Timestep: 0.01667s (60Hz) desktop, 0.0333s (30Hz) mobile

    Related Documentation

    • VehicleController - Main controller component
    • VehicleComponent - Base component class
    • Powertrain - Powertrain system
    • WheelControllerManager (WheelController3D package) - Physics substepping
    • StateSettings - LOD configuration
    • ModuleManager - Module system
    In this article
    Back to top Copyright © NWH - Vehicle Physics, Aerodynamics, Dynamic Water Physics