Search Unity

  1. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  2. Unity 2017.2 beta is now available for download.
    Dismiss Notice
  3. Unity 2017.1 is now released.
    Dismiss Notice
  4. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  5. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  6. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice

How to make a physically real,stable car with WheelColliders

Discussion in 'Editor & General Support' started by Edy, Jun 3, 2010.

  1. dagtholander

    dagtholander

    Joined:
    Oct 28, 2014
    Posts:
    19
    @Edy There's a fault in the wheelcolliders and i don't know how to solve it a good way, I'm making a car simulator and the engine torque is based on torque curves and gearratios and such. However i detected that if you for example assign 300 NM of torque to the wheels it keeps accelerating in infinity, but in real life a engine has a max output that the engine won't go any faster.
    Is there a way of solving this? I don't want to put a top speed that the car won't pass, it would be unrealistic.
     
  2. hemantp

    hemantp

    Joined:
    Feb 10, 2015
    Posts:
    15
    we have make a game like side wheel hero. how to setup the car lift on only two wheel like side wheel hero.

    please give your valuable suggestion
     
  3. ironclutch123

    ironclutch123

    Joined:
    Feb 19, 2015
    Posts:
    50
    Can you please make another version or an optional script we can add to our player so we can enter and exit the vehicle
     
  4. Elharter

    Elharter

    Joined:
    Sep 20, 2015
    Posts:
    27
    Hi,....big big big thanks to you for this amazing tutorial - ive searched around 3 weeks before i found this - and now are all questions answered! big big big thank you!
     
    Edy likes this.
  5. NyaNya

    NyaNya

    Joined:
    Oct 15, 2015
    Posts:
    1
    @Edy Hi~ I come from China.
    I want to know if i can bring this awesome article to my blog (http://blog.csdn.net/u011643833). Translate into Chinese to help more people just like me to make a physically real vehicel easily~
    Full credit to you of cours.

    Hope my poor English can express myself.
    Waiting for your reply. : D
     
  6. SuperUltraHyper

    SuperUltraHyper

    Joined:
    Sep 7, 2015
    Posts:
    69
    So, I have been messing with this script and have an issue. Basically in the instance that one of the wheels becomes ungrounded and the other is still grounded I was getting a weird jerking motion.

    Please help me check me sanity:
    I think this is because as one wheel becomes ungrounded the other exerts an uneven force over the entire vehicle that doesn't result in a twisting motion. This effectively makes the vehicle lighter. At all times you want a Twisting motion. In Order to accurately simulate an Anti-Swaybar you would need access to the vehicles WheelCollider.suspensionSpring function and dynamically adjust the springs tension based on the script's antiRollForce var. You can't manipulate that so so the next best thing is what we are doing. Anyway, in no case should the force make the vehicle lighter / not be a twisting one. Therefore the script should check for "if (groundedL || groundedR)"
    This still isn't ideal because in the instance that the wheel becomes ungrounded it doesn't necessarily mean the travel of the ungrounded wheel is fully extended. I think it's good enough though as the travel will be moving that way in a hurry.

    I'm I Right?

    Updated Script:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AntiRollBar : MonoBehaviour {
    5.  
    6.     public WheelCollider WheelL;
    7.     public WheelCollider WheelR;
    8.     public float AntiRoll = 5000.0f;
    9.  
    10.     public void FixedUpdate()
    11.     {
    12.         WheelHit hit;
    13.         float travelL = 1.0f;
    14.         float travelR = 1.0f;
    15.  
    16.         bool groundedL = WheelL.GetGroundHit(out hit);
    17.         if (groundedL)
    18.             travelL = ( -WheelL.transform.InverseTransformPoint(hit.point).y - WheelL.radius) / WheelL.suspensionDistance;
    19.        
    20.         bool groundedR = WheelR.GetGroundHit(out hit);
    21.         if (groundedR)
    22.             travelR = ( -WheelR.transform.InverseTransformPoint(hit.point).y - WheelR.radius) / WheelR.suspensionDistance;
    23.  
    24.         float antiRollForce = (travelL - travelR) * AntiRoll;
    25.  
    26.         if (groundedL || groundedR)
    27.         {
    28.             GetComponent<Rigidbody>().AddForceAtPosition(WheelL.transform.up * -antiRollForce, WheelL.transform.position);
    29.             GetComponent<Rigidbody>().AddForceAtPosition(WheelR.transform.up * antiRollForce, WheelR.transform.position);
    30.         }
    31.     }
    32. }
    33.  
     
  7. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    828
    Sure, you have my permission. Thank you very much!

    Yes, you are right. This script was a preliminary version, but the version used in EVP4 (Edy's Vehicle Physics for Unity 4) included three operating modes. One of them is the one you're describing: applying both forces whenever any of the wheels are grounded. If fits very good with sports cars. Other mode was applying a force at the grounded wheel and the other at the position of the CoM if the other wheel is lifted.

    Modifying suspensionSpring dynamically wasn't possible in practice in Unity 4. In Unity 5, however, looks like it might work. I haven't tested it yet because EVP for Unity 5 uses a different technique and a single anti-roll setting is included directly in the Vehicle Controller. I plan to experiment with spring forces and anti-roll bars for my other simulation project, Vehicle Physics Pro.

    The anti-roll bar has two main effects on the vehicle:
    1- It translates part of the suspension force from the inner wheel to the outer wheel, reducing the roll angle in curves.
    2- It reduces the overall vehicle elevation in curves (as both suspensions get more compression), which has the effective effect of lowering the center of mass, thus improving stability on curves.

    Both effects might be simulated by modifying suspensionSpring in real time. The problem here is that you'll surely face the issues derived from the Unity 5 WheelCollider failures.

    Some time ago I tested an anti-roll bar implementation that modified the height of the CoM only, with great results. However this solution wouldn't be efficient in Unity 5: modifying the position of the CoM triggers a lot of internal calculations (inertia tensor, sprung masses), so modifying it on each frame would cause a big performance penalty.
     
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    828
    The logic solution here would be applying the torque based on the actual angular velocity of the wheels.

    I can't give better advice, sorry. After some tests I was unable to find any logic on the WheelCollider friction, so I abandoned it and implemented my own friction simulation. I've also designed and implemented a correct engine and drivetrain simulation which applies applies torque + angular velocity correctly.

    I'm afraid that the "drive on two wheels" trick is not possible at this time with Unity 5 WheelCollider. Suspension force is always applied vertically with regards to the rigidbody, no matter the actual situation of the vehicle:

     
  9. ironclutch123

    ironclutch123

    Joined:
    Feb 19, 2015
    Posts:
    50
    I love edy's car physics demo, I cant buy the full version though, do you thing you could make a free version with like 1 car or some limitation?
     
    cholasimmons likes this.
  10. cholasimmons

    cholasimmons

    Joined:
    Dec 17, 2015
    Posts:
    3
    just thought I'd post an updated script, I converted this from java to C# myself, thought it was a big deal last night, lol (Unity 5.3.5f1)
    However this causes my car to rise up in the air off the ground when I steer left, right brings it back down to Earth.


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AntiRoll : MonoBehaviour {
    5.  
    6.     public WheelCollider WheelL;
    7.     public WheelCollider WheelR;
    8.     public float AntiRollValue = 3000;
    9.  
    10.     // Update is called once per frame
    11.     void FixedUpdate ()
    12.     {
    13.         WheelHit hit;
    14.         float travelL = 1.0F;
    15.         float travelR = 1.0F;
    16.  
    17.         bool groundedL = WheelL.GetGroundHit (out hit);
    18.         if (groundedL) {
    19.             travelL = (-WheelL.transform.InverseTransformPoint (hit.point).y - WheelL.radius) / WheelL.suspensionDistance;
    20.         }
    21.         bool groundedR = WheelR.GetGroundHit (out hit);
    22.         if (groundedR) {
    23.             travelR = (-WheelR.transform.InverseTransformPoint (hit.point).y - WheelR.radius) / WheelR.suspensionDistance;
    24.         }
    25.  
    26.         float antiRollForce = (travelL - travelR) * AntiRollValue;
    27.         if(groundedL){
    28.             GetComponent<Rigidbody>().AddForceAtPosition(WheelL.transform.up * -antiRollForce, WheelL.transform.position);
    29.         }
    30.         if(groundedR){
    31.             GetComponent<Rigidbody>().AddForceAtPosition(WheelR.transform.up * -antiRollForce, WheelR.transform.position);
    32.         }
    33.     }
    34. }
    35.  
     
    Edy likes this.
  11. ricardHagerman

    ricardHagerman

    Joined:
    May 26, 2014
    Posts:
    3
    this works in unity 5.5

    Code (CSharp):
    1.  
    2.  
    3. using UnityEngine;
    4.  
    5. public class SwayBar : MonoBehaviour
    6. {
    7.     public WheelCollider[] wheels;
    8.     Rigidbody rb;
    9.     WheelAxle frontAxle;
    10.     WheelAxle rearAxle;
    11.     public float antiRollFront = 3000f;
    12.     public float antiRollRear = 3000f;
    13.  
    14.     void Start()
    15.     {
    16.         frontAxle= new WheelAxel { LeftWheel = wheels[0], RightWheel = wheels[1], AntiRollForce = antiRollFront };
    17.         rearAxle = new WheelAxel { LeftWheel = wheels[2], RightWheel = wheels[3], AntiRollForce = antiRollRear };
    18.         rb = GetComponent<Rigidbody>();
    19.     }
    20.  
    21.     void FixedUpdate()
    22.     {
    23.         WheelHit hit;
    24.         foreach (var wheel in wheels)
    25.             if (wheel.GetGroundHit(out hit))
    26.                 rb.AddForceAtPosition(wheel.transform.up * AntiRollForce(wheel), wheel.transform.position);
    27.     }
    28.  
    29.     float AntiRollForce(WheelCollider wheel)
    30.     {
    31.         WheelAxle axle;
    32.         if (frontAxle.LeftWheel == wheel || frontAxle.RightWheel == wheel)
    33.             axle = frontAxle;
    34.         else
    35.             axle = rearAxle;
    36.         WheelHit hit;
    37.         var travelL = 1f;
    38.         var travelR = 1f;
    39.         if (axle.LeftWheel.GetGroundHit(out hit))
    40.             travelL = (-axle.LeftWheel.transform.InverseTransformPoint(hit.point).y - axle.LeftWheel.radius) / axle.LeftWheel.suspensionDistance;
    41.         if (axle.RightWheel.GetGroundHit(out hit))
    42.             travelR = (-axle.RightWheel.transform.InverseTransformPoint(hit.point).y - axle.RightWheel.radius) / axle.RightWheel.suspensionDistance;
    43.         if (wheel == axle.LeftWheel)
    44.             return -(travelL - travelR) * axel.AntiRollForce;
    45.         return (travelL - travelR) * axel.AntiRollForce;
    46.     }
    47. }
    48.  
    combined with this struct

    Code (CSharp):
    1.  
    2.  
    3. using UnityEngine;
    4.  
    5. struct WheelAxle
    6. {
    7.     public WheelCollider LeftWheel { get; set; }
    8.     public WheelCollider RightWheel { get; set; }
    9.     public float AntiRollForce { get; set; }
    10. }
    11.  
    NB: put the wheels in to the wheelColliderArray in the right order (FL,FR,RL,RR)
     
    Last edited: Dec 9, 2016
    aliyeredon2 and Edy like this.
  12. aliyeredon2

    aliyeredon2

    Joined:
    Mar 31, 2015
    Posts:
    1,334
    Thank you. WheelAxel are WheelAxle in line 16 and 17. Also line 52-53 are axle.
     
  13. Banksy

    Banksy

    Joined:
    Mar 31, 2013
    Posts:
    253
    hhmm... so how do I save a struct ?

    Do i save it in a separate script or add to the top of my car's physics script ??
     
  14. aliyeredon2

    aliyeredon2

    Joined:
    Mar 31, 2015
    Posts:
    1,334
    Separate script is easier.
     
  15. AnupamSahu

    AnupamSahu

    Joined:
    May 16, 2015
    Posts:
    7
    hey, thanks for this wonderful tutorial..
    but, there's a tiny problem.. when you rapidly turn the steering left to right.. the car looses control, kind of oscillates and turns around..
    i know this is a realistic simulator, but it isn't desirable in a racing game where ease of control dominates realism..
    any ideas on how I can solve this problem?
    btw, i use Unity 5.6
     
  16. aliyeredon2

    aliyeredon2

    Joined:
    Mar 31, 2015
    Posts:
    1,334
    You can change sideways friction values to slide the car when turning on high
     
  17. nawash

    nawash

    Joined:
    Jan 29, 2010
    Posts:
    141