Search Unity

3D to 2D vehicle raycast

Discussion in 'Physics' started by gabdab2017, Sep 12, 2020.

  1. gabdab2017

    gabdab2017

    Joined:
    Nov 27, 2017
    Posts:
    4
    3D vehicle raycast
    https://github.com/unity-car-tutorials/SimpleRaycastVehicle-Unity
    How to port it to 2D?
    It all resolves to wheels (RaycastWheel.cs):
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. // Do test the code! You usually need to change a few small bits.
    5.  
    6. [RequireComponent(typeof(Rigidbody))]  
    7. public class RaycastWheel : MonoBehaviour {
    8.  
    9.     // More advanced Vehicle Raycast wheel
    10.  
    11.     public Transform graphic;
    12.  
    13.     public float mass = 1.00f;
    14.     public float wheelRadius  = 0.5f;
    15.     public float suspensionRange  = 0.10f;
    16.     public float suspensionForce  = 0.00f;
    17.     public float suspensionDamp  = 0.00f;
    18.     public float compressionFrictionFactor  = 0.00f;
    19.  
    20.     public float sidewaysFriction  = 0.00f;
    21.     public float sidewaysDamp  = 0.00f;
    22.     public float sidewaysSlipVelocity  = 0.00f;
    23.     public float sidewaysSlipForce  = 0.00f;
    24.     public float sidewaysSlipFriction  = 0.00f;
    25.     public float sidewaysStiffnessFactor  = 0.00f;
    26.  
    27.     public float forwardFriction  = 0.00f;
    28.     public float forwardSlipVelocity  = 0.00f;
    29.     public float forwardSlipForce  = 0.00f;
    30.     public float forwardSlipFriction  = 0.00f;
    31.     public float forwardStiffnessFactor  = 0.00f;
    32.  
    33.     public float frictionSmoothing  = 1.00f;
    34.  
    35.     public float usedSideFriction  = 0.00f;
    36.     public float usedForwardFriction  = 0.00f;
    37.     public float sideSlip  = 0.00f;
    38.     public float forwardSlip  = 0.00f;
    39.  
    40.     public bool driven  = false;
    41.     public bool brake  = false;
    42.     public bool skidbrake  = false;
    43.  
    44.     public float speed  = 0.00f;
    45.  
    46.     private RaycastHit hit;
    47.  
    48.     private Rigidbody parent;
    49.  
    50.     private float wheelCircumference = 0.00f;
    51.  
    52.     private bool grounded = false;
    53.  
    54.     public bool IsGrounded
    55.     {
    56.         get
    57.         {
    58.             return grounded;
    59.         }
    60.     }
    61.  
    62.     void Start ()
    63.     {
    64.         wheelCircumference = wheelRadius * Mathf.PI * 2;
    65.         parent = transform.root.GetComponent<Rigidbody>();
    66.     }
    67.  
    68.     void  FixedUpdate ()
    69.     {
    70.         // the object this script is attached to does not move. This ray is like imagining
    71.         // that the shock is compressed as much as possible, and then extends out as far as it can before it hits the ground.
    72.         // If it doesn't, then the wheel is fully extended.
    73.  
    74.         Vector3 down = transform.TransformDirection(Vector3.down);
    75.  
    76.         // if raycast from position downwards with range suspensionrange + wheelRadius
    77.         // and hit.collider != the parent (car)
    78.  
    79.         // calculate the force of the shock as it pushes on the car and the earth due to compression.
    80.         // Since the earth does not move, this is an upward force on the car only
    81.  
    82.         if(Physics.Raycast (transform.position, down, out hit, suspensionRange + wheelRadius) && hit.collider.transform.root != transform.root)
    83.         {
    84.             // how fast is the wheel moving relative to the ground, without taking the wheel's rotation into account
    85.             Vector3 velocityAtTouch = parent.GetPointVelocity(hit.point);
    86.  
    87.             // calculate spring compression
    88.             // difference in positions divided by total suspension range
    89.             float compression = hit.distance / (suspensionRange + wheelRadius);
    90.             compression = -compression + 1;
    91.  
    92.             // final force
    93.             Vector3 force = -down * compression * suspensionForce;
    94.  
    95.        
    96.             // velocity at point of contact transformed into local space
    97.             Vector3 t = transform.InverseTransformDirection(velocityAtTouch);
    98.  
    99.             // local x and z directions = 0
    100.             // Here we set t equal to the speed at which the shock is contracting / expanding
    101.             t.z = 0;
    102.             t.x = 0;
    103.  
    104.             // back to world space * -damping
    105.             // this force simulates the force exerted by the friction in the suspension.
    106.             Vector3 shockDrag = transform.TransformDirection(t) * -suspensionDamp;
    107.  
    108.             // forwardDifference = local speed along the z axis
    109.             // the difference between the speed of the ground and the wheel taking rotation + the car's velocity into account.
    110.             // (in local space, that means, relative to the wheel. So if you were standing on the wheel surface,
    111.             // how fast would you percieve the ground moving? Either squashing you every time the wheel goes around
    112.             // (not skidding, absolute value close to zero) or scrapping you to bits (skidding, large absolute value))
    113.  
    114.             float forwardDifference = transform.InverseTransformDirection(velocityAtTouch).z - speed;
    115.  
    116.             // newForwardFriction = interpolated between forwardFriction (constant) and
    117.             // forwardSlipFriction. Interpolation is forwardSlip squared.
    118.             // so if forwardSlip = 1, newForwardFriction = forwardSlipFriction
    119.  
    120.  
    121.             //Ok, this next part is not related to real physics an any way whatsoever. Ummm... Basically the friction that the wheel has with
    122.             // the ground changes (using a lerp function over time) depending on the current friction force.
    123.             // I guess this simulates how once a car starts skidding, the friction goes down so it skids more.
    124.             // __________________z-friction__________________
    125.             // move the current working friction value toward the minimum about porportional to the "skidding-ness" squared
    126.  
    127.             float newForwardFriction = Mathf.Lerp(forwardFriction, forwardSlipFriction, forwardSlip * forwardSlip);
    128.  
    129.             // increase the current working friction value depending on how hard the shock is pressing the wheel against the ground
    130.             newForwardFriction = Mathf.Lerp(newForwardFriction, newForwardFriction * compression * 1, compressionFrictionFactor);
    131.  
    132.             if(frictionSmoothing > 0)
    133.                 usedForwardFriction = Mathf.Lerp(usedForwardFriction, newForwardFriction, Time.fixedDeltaTime / frictionSmoothing);
    134.             else
    135.                 usedForwardFriction = newForwardFriction;
    136.  
    137.             // calculate one component of the friction force: the difference between the wheel surface velocity and ground surface
    138.             // velocity times friction (not based on real physics AFAIK)
    139.             Vector3 forwardForce = transform.TransformDirection(new Vector3(0, 0, -forwardDifference)) * usedForwardFriction;
    140.  
    141.             // calculate how much we be slippin  (if the force is high, the tire will give and slip on the road)
    142.             forwardSlip = Mathf.Lerp(forwardForce.magnitude / forwardSlipForce, forwardDifference / forwardSlipVelocity, forwardStiffnessFactor);
    143.  
    144.             float sidewaysDifference = transform.InverseTransformDirection(velocityAtTouch).x;
    145.             float newSideFriction = Mathf.Lerp(sidewaysFriction, sidewaysSlipFriction, sideSlip * sideSlip);
    146.             newSideFriction = Mathf.Lerp(newSideFriction, newSideFriction * compression * 1, compressionFrictionFactor);
    147.  
    148.             if(frictionSmoothing > 0)
    149.                 usedSideFriction = Mathf.Lerp(usedSideFriction, newSideFriction, Time.fixedDeltaTime / frictionSmoothing);
    150.             else
    151.                 usedSideFriction = newSideFriction;
    152.  
    153.             // ____________________________________
    154.             // this is much the same as the block above, but for the x-axis
    155.             // __________________x-friction__________________
    156.  
    157.             Vector3 sideForce = transform.TransformDirection(new Vector3(-sidewaysDifference, 0, 0)) * usedSideFriction;
    158.             sideSlip = Mathf.Lerp(sideForce.magnitude / sidewaysSlipForce, sidewaysDifference / sidewaysSlipVelocity, sidewaysStiffnessFactor);
    159.  
    160.             // this thing is totally made up. It's as if god's hand nudges the car back on course whenever it is moving sideways,
    161.             // by a factor of sidewaysDamp
    162.             t = transform.InverseTransformDirection(velocityAtTouch);
    163.             t.z = 0;
    164.             t.y = 0;
    165.  
    166.             Vector3 sideDrag = transform.TransformDirection(t) * -sidewaysDamp;
    167.  
    168.             // By the some of all you combined, I become CAPTAIN FORCE
    169.             parent.AddForceAtPosition(force + shockDrag - forwardForce + sideForce + sideDrag, transform.position);
    170.  
    171.  
    172.             // for every action there is an opposite reaction: the wheel adds a force on the ground, but the ground does not move,
    173.             // so that force is added to the car instead in the opposite direction (this lets the engine propel the thing forward).
    174.             // But!!! we also have to add a force on the engine, because otherwise we'd be adding force from nothing.
    175.             // The opposite reaction is this force on the motor. The motor is not a rigidbody, it is a made up thing in the Car.js script
    176.             if(driven)
    177.             {
    178.                 //car.AddForceOnMotor (forwardDifference * usedForwardFriction * Time.fixedDeltaTime);
    179.             }
    180.             else
    181.             speed += forwardDifference;  
    182.  
    183.             graphic.position = transform.position + (down * (hit.distance - wheelRadius));
    184.         }
    185.         else
    186.         {
    187.             graphic.position = transform.position + (down * suspensionRange);
    188.         }
    189.  
    190.         speed = parent.velocity.magnitude;
    191.  
    192.         graphic.transform.Rotate(360 * (speed / wheelCircumference) * Time.fixedDeltaTime, 0, 0);
    193.     }
    194.  
    195.     void  OnDrawGizmosSelected ()
    196.     {
    197.         Gizmos.color = new Color(0,1,0,1);
    198.         Vector3 direction = transform.TransformDirection (-Vector3.up) * (this.wheelRadius);
    199.         Gizmos.DrawRay(transform.position,direction);
    200.  
    201.         Gizmos.color = new Color(0,0,1,1);
    202.         direction = transform.TransformDirection (-Vector3.up) * (this.suspensionRange);
    203.         Gizmos.DrawRay(new Vector3(transform.position.x,transform.position.y - wheelRadius,transform.position.z),direction);
    204.     }
    205. }