Search Unity

How do you make the wheel mesh follow the wheelcolliders?

Discussion in 'Scripting' started by knookle89, Feb 14, 2013.

  1. knookle89

    knookle89

    Joined:
    Feb 13, 2013
    Posts:
    42
    I found this under unity answers:
    http://answers.unity3d.com/questions/21319/mapping-movement-to-a-wheelcollider-suspension.html
    The issues is when i add the code to the function update area i get all types of errors.
    Here is the code from the link.
    Code (csharp):
    1.     var hit : RaycastHit;
    2.      
    3.     if (Physics.Raycast(Wheel.transform.position, -Wheel.transform.up, hit, Wheel.suspensionDistance + Wheel.radius))
    4.     WheelMesh.position = hit.point + Wheel.transform.up * Wheel.radius;
    5.     else
    6.     WheelMesh.position = Wheel.transform.position - (Wheel.transform.up * WheelCol.suspensionDistance);
    Most of the errors say, unknown identifier 'Wheel' or unknown identifier 'WheelMesh or unknown identifier 'Wheelcol'
    Is there variables not set? I'm guessing WheelMesh is the Object and Wheelcol is the WheelCollider
     
  2. lockbox

    lockbox

    Joined:
    Feb 10, 2012
    Posts:
    519
  3. knookle89

    knookle89

    Joined:
    Feb 13, 2013
    Posts:
    42
    Ya thanks again lockbox. It seems that the wheels are following the colliders. The front is even steering now. Note that you must put the wheels mesh and colliders both where the suspension is fully compressed(at the top of the stroke). Then it works perfect.
     
  4. vbs

    vbs

    Joined:
    Sep 8, 2014
    Posts:
    24
    I was searching for some code examples to deal with using wheel colliders and making wheel meshes follow the suspensions of these coliders. I've seen plenty of JS examples, so I extracted an example into C# and I'm posting it here for anyone else that is interested in a quick solution as well.

    Instructions: Make a Wheel.cs script file and drop it on top of each of your wheel meshes, or empty game objects that hold each of your wheel meshes (as in my case).

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Wheel : MonoBehaviour {
    6.  
    7.   public WheelCollider wheelC;
    8.  
    9.   private Vector3 wheelCCenter;
    10.   private RaycastHit hit;
    11.  
    12.   void Start () {
    13.  
    14.   }
    15.  
    16.   void Update () {
    17.     wheelCCenter = wheelC.transform.TransformPoint(wheelC.center);
    18.  
    19.     if ( Physics.Raycast(wheelCCenter, -wheelC.transform.up, out hit, wheelC.suspensionDistance + wheelC.radius) ) {
    20.       transform.position = hit.point + (wheelC.transform.up * wheelC.radius);
    21.     } else {
    22.       transform.position = wheelCCenter - (wheelC.transform.up * wheelC.suspensionDistance);
    23.     }
    24.   }
    25.  
    26.   void FixedUpdate() {
    27.  
    28.   }
    29. }
    30.  
    31.  
    Credit: I extracted the code from this JS example: https://dl.dropboxusercontent.com/u/16956434/Car_Tutorial_Scripts/WheelAlignment_Script.js
     
  5. alamay

    alamay

    Joined:
    Nov 17, 2014
    Posts:
    2
    Perfect!!! Thanks!!!!
     
  6. Beauchamp

    Beauchamp

    Joined:
    Aug 11, 2014
    Posts:
    5
    Finally this works for me, great man!!! ty!!!
     
  7. RichardRevesz

    RichardRevesz

    Joined:
    Jul 4, 2018
    Posts:
    12
    Usually it is not really visible, but not only the position, the rotation lags a bit as well.
    It can be bothering when you are drifting, and the rear wheels are not looking forward, but seems like it was a bit steered.
    If you want to eliminate the rotation lag as well, use this extended version of vbs' code.

    Note that Unity updates frames in the following order: FixedUpdate, Update, Physics, LateUpdate.
    If you want to adjust something to physics, you usually get the best results with LateUpdate, as physics are already calculated.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class WheelLagCompensation : MonoBehaviour
    5. {
    6.  
    7.     public WheelCollider wheelC;
    8.     private Vector3 wheelCCenter;
    9.     private Quaternion wheelCForward;
    10.     private RaycastHit hit;
    11.     float rotation;
    12.  
    13.     void LateUpdate()
    14.     {
    15.         wheelCCenter = wheelC.transform.TransformPoint(wheelC.center);
    16.         wheelCForward = wheelC.transform.rotation;
    17.         float steerAngle = wheelC.steerAngle;
    18.         rotation += Mathf.Rad2Deg*(2*Mathf.PI*wheelC.rpm/60*Time.deltaTime);
    19.         Quaternion rot = new Quaternion();
    20.         rot = Quaternion.Euler(rotation, steerAngle, 0);
    21.  
    22.         if (Physics.Raycast(wheelCCenter, -wheelC.transform.up, out hit, wheelC.suspensionDistance + wheelC.radius))
    23.         {
    24.             transform.position = hit.point + (wheelC.transform.up * wheelC.radius);
    25.             transform.rotation = wheelCForward * rot;
    26.         }
    27.         else
    28.         {
    29.             transform.position = wheelCCenter - (wheelC.transform.up * wheelC.suspensionDistance);
    30.             transform.rotation = wheelCForward * rot;
    31.         }
    32.     }
    33. }
     
  8. juelzsantana123

    juelzsantana123

    Joined:
    Feb 28, 2019
    Posts:
    17
    Wow you put in update method such complicated calculations.
    This is my code that i copied somewhere and then changed a little.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityStandardAssets.CrossPlatformInput;
    3.  
    4. public class CarMove : MonoBehaviour
    5. {
    6.    [SerializeField] float m_horizontalInput;
    7.     [SerializeField] float m_verticalInput;
    8.     float m_steeringAngle;
    9.  
    10.     [SerializeField] WheelCollider frontDriverW, frontPassengerW;
    11.     [SerializeField] WheelCollider rearDriverW, rearPassengerW;
    12.     [SerializeField] Transform frontDriverT, frontPassengerT;
    13.     [SerializeField] Transform rearDriverT, rearPassengerT;
    14.     [SerializeField] float maxSteerAngle = 30;
    15.     [SerializeField] float motorForce = 50;
    16.  
    17.     public void GetInput()
    18.     {
    19.         m_horizontalInput = CrossPlatformInputManager.GetAxis("Horizontal");
    20.         m_verticalInput = CrossPlatformInputManager.GetAxis("Vertical");
    21.     }
    22.  
    23.     private void Steer()
    24.     {
    25.         switch (m_horizontalInput)
    26.         {
    27.             case -1:
    28.                 m_steeringAngle = maxSteerAngle * m_horizontalInput;
    29.                 frontDriverW.steerAngle = frontPassengerW.steerAngle = m_steeringAngle;
    30.                 break;
    31.             case 1:
    32.                 m_steeringAngle = maxSteerAngle * m_horizontalInput;
    33.                 frontDriverW.steerAngle = frontPassengerW.steerAngle = m_steeringAngle;
    34.                 break;
    35.             default:
    36.                 frontDriverW.steerAngle = frontPassengerW.steerAngle = 0;
    37.                 break;
    38.      }
    39.          
    40.      
    41.  
    42.      
    43.     }
    44.  
    45.     private void Accelerate()
    46.     { switch (m_verticalInput)
    47.         {
    48.             case 1: rearPassengerW.motorTorque = rearDriverW.motorTorque = motorForce; break;
    49.             case -1: rearPassengerW.motorTorque = rearDriverW.motorTorque = -motorForce; break;
    50.             case 0: rearPassengerW.motorTorque = rearDriverW.motorTorque = 0; break;
    51.        default: return;
    52.         }
    53.      
    54.     }
    55.  
    56.       private void UpdateWheelPoses()
    57.     {
    58.         UpdateWheelPose(frontDriverW, frontDriverT);
    59.         UpdateWheelPose(frontPassengerW, frontPassengerT);
    60.         UpdateWheelPose(rearDriverW, rearDriverT);
    61.         UpdateWheelPose(rearPassengerW, rearPassengerT);
    62.     }
    63.  
    64.   private void UpdateWheelPose(WheelCollider _collider, Transform _transform)
    65.     {
    66.         Vector3 _pos = _transform.position;
    67.         Quaternion _quat = _transform.rotation;
    68.  
    69.        _collider.GetWorldPose(out _pos, out _quat);
    70.  
    71.         _transform.position = _pos;
    72.         _transform.rotation = _quat;
    73.     }
    74.  
    75.     private void Update()
    76.     {
    77.         GetInput();
    78.         Steer();
    79.         Accelerate();
    80.         UpdateWheelPoses();
    81.     }
     
  9. zezba9000

    zezba9000

    Joined:
    Sep 28, 2010
    Posts:
    985
    "WheelCollider.GetWorldPose(...)" is the simple answer to this.
     
    Robert-O, EeJayEn, Deneb and 3 others like this.