NWH Common
Search Results for

    Utilities

    NWH Common provides utility classes for math, geometry, unit conversion, and control systems.

    MathUtility

    Mathematical operations commonly needed in physics simulations.

    Clamping and Wrapping

    using NWH.Common.Utility;
    
    // Clamp value between min and max
    float clamped = MathUtility.Clamp(value, min, max);
    
    // Clamp01 (between 0 and 1)
    float normalized = MathUtility.Clamp01(value);
    
    // Wrap angle to -180 to 180 range
    float angle = MathUtility.WrapAngle(angle);
    
    // Wrap value to any range
    float wrapped = MathUtility.Wrap(value, min, max);
    

    Interpolation

    // Smooth interpolation (similar to Mathf.SmoothDamp)
    float smoothed = MathUtility.SmoothStep(from, to, t);
    
    // Inverse lerp with clamping
    float t = MathUtility.InverseLerp(a, b, value);
    
    // Remap value from one range to another
    float remapped = MathUtility.Remap(value, fromMin, fromMax, toMin, toMax);
    

    Comparison

    // Approximately equal with tolerance
    bool isEqual = MathUtility.Approximately(a, b, tolerance);
    
    // Check if value within range
    bool inRange = MathUtility.InRange(value, min, max);
    
    // Sign function (-1, 0, or 1)
    int sign = MathUtility.Sign(value);
    

    Common Physics Calculations

    // Calculate spring force
    float springForce = MathUtility.SpringForce(
        currentLength,
        restLength,
        springRate,
        damping,
        velocity
    );
    
    // Calculate damper force
    float damperForce = MathUtility.DamperForce(
        velocity,
        damperRate
    );
    
    // Apply exponential smoothing
    float smoothed = MathUtility.ExponentialSmooth(
        currentValue,
        targetValue,
        smoothTime,
        deltaTime
    );
    

    GeomUtility

    Geometry calculations for physics and collision detection.

    Distance Calculations

    using NWH.Common.Utility;
    
    // Distance from point to line segment
    float distance = GeomUtility.DistanceToLineSegment(
        point,
        lineStart,
        lineEnd,
        out Vector3 closestPoint
    );
    
    // Distance from point to plane
    float distance = GeomUtility.DistanceToPlane(
        point,
        planeNormal,
        planePoint
    );
    
    // Closest point on line segment
    Vector3 closest = GeomUtility.ClosestPointOnLineSegment(
        point,
        lineStart,
        lineEnd
    );
    

    Intersection Tests

    // Line-plane intersection
    bool intersects = GeomUtility.LinePlaneIntersection(
        lineStart,
        lineEnd,
        planeNormal,
        planePoint,
        out Vector3 intersectionPoint
    );
    
    // Ray-sphere intersection
    bool intersects = GeomUtility.RaySphereIntersection(
        rayOrigin,
        rayDirection,
        sphereCenter,
        sphereRadius,
        out float distance
    );
    
    // AABB (box) intersection
    bool intersects = GeomUtility.AABBIntersection(
        box1Min,
        box1Max,
        box2Min,
        box2Max
    );
    

    Projections

    // Project point onto plane
    Vector3 projected = GeomUtility.ProjectPointOnPlane(
        point,
        planeNormal,
        planePoint
    );
    
    // Project vector onto another vector
    Vector3 projected = GeomUtility.ProjectVector(
        vector,
        ontoVector
    );
    
    // Project point onto line
    Vector3 projected = GeomUtility.ProjectPointOnLine(
        point,
        lineStart,
        lineDirection
    );
    

    Area and Volume

    // Triangle area
    float area = GeomUtility.TriangleArea(
        vertexA,
        vertexB,
        vertexC
    );
    
    // Polygon area (2D)
    float area = GeomUtility.PolygonArea(vertices);
    
    // Sphere volume
    float volume = GeomUtility.SphereVolume(radius);
    
    // Box volume
    float volume = GeomUtility.BoxVolume(size);
    

    UnitConverter

    Convert between different unit systems.

    Speed Conversions

    using NWH.Common.Utility;
    
    // m/s to km/h
    float kmh = UnitConverter.MsToKmh(metersPerSecond);
    
    // m/s to mph
    float mph = UnitConverter.MsToMph(metersPerSecond);
    
    // km/h to m/s
    float ms = UnitConverter.KmhToMs(kilometersPerHour);
    
    // mph to m/s
    float ms = UnitConverter.MphToMs(milesPerHour);
    

    Torque and Power

    // Nm to lb-ft
    float lbft = UnitConverter.NmToLbft(newtonMeters);
    
    // lb-ft to Nm
    float nm = UnitConverter.LbftToNm(poundFeet);
    
    // kW to HP
    float hp = UnitConverter.KwToHp(kilowatts);
    
    // HP to kW
    float kw = UnitConverter.HpToKw(horsepower);
    
    // Calculate power from torque and RPM
    float power = UnitConverter.PowerFromTorqueAndRpm(torque, rpm);
    

    Weight and Mass

    // kg to lbs
    float lbs = UnitConverter.KgToLbs(kilograms);
    
    // lbs to kg
    float kg = UnitConverter.LbsToKg(pounds);
    

    Distance

    // meters to feet
    float feet = UnitConverter.MetersToFeet(meters);
    
    // feet to meters
    float meters = UnitConverter.FeetToMeters(feet);
    
    // meters to miles
    float miles = UnitConverter.MetersToMiles(meters);
    
    // miles to meters
    float meters = UnitConverter.MilesToMeters(miles);
    

    Temperature

    // Celsius to Fahrenheit
    float f = UnitConverter.CelsiusToFahrenheit(celsius);
    
    // Fahrenheit to Celsius
    float c = UnitConverter.FahrenheitToCelsius(fahrenheit);
    
    // Celsius to Kelvin
    float k = UnitConverter.CelsiusToKelvin(celsius);
    

    Usage Example

    public class Speedometer : MonoBehaviour
    {
        public Rigidbody vehicle;
        public Text speedText;
        public bool useImperialUnits = false;
    
        void Update()
        {
            float speed = vehicle.velocity.magnitude;
    
            if (useImperialUnits)
            {
                float mph = UnitConverter.MsToMph(speed);
                speedText.text = $"{mph:F1} mph";
            }
            else
            {
                float kmh = UnitConverter.MsToKmh(speed);
                speedText.text = $"{kmh:F1} km/h";
            }
        }
    }
    

    PIDController

    Proportional-Integral-Derivative controller for smooth control systems.

    Overview

    PID controllers are used for:

    • Smooth throttle/brake control
    • Cruise control systems
    • Automatic steering
    • Any feedback control system

    Setup

    using NWH.Common.Utility;
    
    // Create PID controller
    PIDController pid = new PIDController();
    
    // Configure gains
    pid.Kp = 1.0f;   // Proportional gain
    pid.Ki = 0.1f;   // Integral gain
    pid.Kd = 0.05f;  // Derivative gain
    
    // Optional: Set output limits
    pid.outputMin = -1f;
    pid.outputMax = 1f;
    

    Usage

    void FixedUpdate()
    {
        float targetSpeed = 20f;  // m/s
        float currentSpeed = rigidbody.velocity.magnitude;
    
        // Calculate control output
        float throttle = pid.Update(
            targetSpeed,
            currentSpeed,
            Time.fixedDeltaTime
        );
    
        // Apply throttle to vehicle
        ApplyThrottle(throttle);
    }
    

    Tuning PID Gains

    Proportional (Kp):

    • Affects immediate response
    • Higher = more aggressive, may oscillate
    • Start with 1.0, increase if too slow

    Integral (Ki):

    • Eliminates steady-state error
    • Higher = faster elimination, may overshoot
    • Start with 0, increase if error persists

    Derivative (Kd):

    • Reduces overshoot and oscillation
    • Higher = more damping, may be sluggish
    • Start with 0, increase if oscillating

    Tuning Process:

    1. Set all to 0
    2. Increase Kp until system responds
    3. Add Kd to reduce oscillation
    4. Add Ki if steady-state error exists

    Reset

    Reset integral accumulation when setpoint changes:

    pid.Reset();
    target = newTarget;
    

    Example: Cruise Control

    public class CruiseControl : MonoBehaviour
    {
        private PIDController speedPID;
        public float cruiseSpeed = 25f;  // m/s
        public bool enabled = false;
    
        void Start()
        {
            speedPID = new PIDController
            {
                Kp = 0.5f,
                Ki = 0.05f,
                Kd = 0.1f,
                outputMin = 0f,
                outputMax = 1f
            };
        }
    
        void FixedUpdate()
        {
            if (!enabled) return;
    
            float currentSpeed = GetComponent<Rigidbody>().velocity.magnitude;
    
            float throttle = speedPID.Update(
                cruiseSpeed,
                currentSpeed,
                Time.fixedDeltaTime
            );
    
            ApplyThrottle(throttle);
        }
    
        public void SetCruiseSpeed(float speed)
        {
            cruiseSpeed = speed;
            speedPID.Reset();
        }
    }
    

    Common Usage Patterns

    Speed Display with Units

    public class SpeedDisplay : MonoBehaviour
    {
        public enum SpeedUnit { MetersPerSecond, KilometersPerHour, MilesPerHour }
        public SpeedUnit displayUnit = SpeedUnit.KilometersPerHour;
    
        public string GetSpeedText(float speedMs)
        {
            switch (displayUnit)
            {
                case SpeedUnit.MetersPerSecond:
                    return $"{speedMs:F1} m/s";
    
                case SpeedUnit.KilometersPerHour:
                    return $"{UnitConverter.MsToKmh(speedMs):F0} km/h";
    
                case SpeedUnit.MilesPerHour:
                    return $"{UnitConverter.MsToMph(speedMs):F0} mph";
    
                default:
                    return $"{speedMs:F1} m/s";
            }
        }
    }
    

    Smooth Camera Follow

    public class SmoothFollow : MonoBehaviour
    {
        public Transform target;
        public float smoothTime = 0.3f;
    
        void LateUpdate()
        {
            Vector3 targetPosition = target.position + offset;
    
            transform.position = MathUtility.ExponentialSmooth(
                transform.position,
                targetPosition,
                smoothTime,
                Time.deltaTime
            );
        }
    }
    

    Ground Detection

    public class GroundCheck : MonoBehaviour
    {
        public float rayLength = 1f;
    
        public bool IsGrounded()
        {
            RaycastHit hit;
            bool grounded = Physics.Raycast(
                transform.position,
                -transform.up,
                out hit,
                rayLength
            );
    
            if (grounded)
            {
                float distance = GeomUtility.DistanceToPlane(
                    transform.position,
                    hit.normal,
                    hit.point
                );
    
                return distance < 0.1f;
            }
    
            return false;
        }
    }
    

    Performance Notes

    • MathUtility - All methods are static, no allocations
    • GeomUtility - Some methods use out parameters to avoid allocations
    • UnitConverter - Simple multiplications, very fast
    • PIDController - Lightweight, suitable for many instances

    API Reference

    For detailed API documentation, refer to the complete API reference in the navigation menu:

    • <xref:NWH.Common.Utility.MathUtility>
    • GeomUtility
    • UnitConverter
    • PIDController

    See Also

    • Input System - For implementing input-based control systems with PIDController
    • Camera System - For smooth camera follow techniques using MathUtility
    • Variable Center of Mass - Related physics calculations
    • Shifting Origin - Large world coordinate systems with distance calculations
    • Edit this page
    In this article
    Back to top Copyright © NWH - Vehicle Physics, Aerodynamics, Dynamic Water Physics