Learning wheel colliders
Tags: gamedev, unity3d
Published: 2022-12-27 21:29:27

Learning to develop a wheel collider in Unity seems rather intimidating at first.  There is an awful lot of physics at play translated into a 3D digital space, and when thinking about the broad range of driving games out there with all the different handling characteristics, it seems that one could spend decades tweaking and perfecting the perfect driving model.

So in aim of speeding up the development process, in this blog post, I'll go over the basics of using the out of the box tools within Unity for creating a wheel collider, and share my thoughts and feedback on my experience.

I'm working in a new 3D project in Unity. I already have setup a large plane object to act as the ground for the car to drive on. In your project, you'll want to create a new empty game object and name it "car_root" or something to that effect. This will be the parent object for all of your vehicle's components, including the wheel geometry, colliders etc.

Next we can create the body of the car as a child of "car_root".  I'm using the ol' aerodynamic brick model of a cube, scaled out to the rough size of a car (3.9m x 1.75m x 1.23m).

Next, we can create a new empty game object called "wheels" as a child of "car_root".  This will act as our reference container for our wheel assets. You'll want to create four more empty game objects and name them "fronLeft," "frontRight", "rearLeft", and "rearRight". These will be the objects that the wheel colliders will be attached to.  Make sure to adjust the transform position of each wheel to suit the desired geometry of the car. One important thing to note is that the wheel colliders should be positioned so that they are centered on the wheels. If the colliders are not properly aligned, your vehicle may behave strangely or even become uncontrollable.

Then, to create the wheel colliders themselves, you'll need to add a "Wheel Collider" component to each of the four wheel objects. You can do this by right-clicking on the object and selecting "Add Component" from the context menu.

Once you've added the wheel collider component to all four wheels, you'll need to adjust the settings to match your vehicle's specifications. This includes things like the radius and width of the wheels, the suspension spring strength, and the mass of the wheels.  For now, I'm sticking with the pure out of the box values.

At the moment, this just gives us a simple model of a car with a body, and some invisible wheels.  So lets add some wheel geometry in so we can see the actual wheels.  As a child of each wheel collider game object, create a cylinder game object, and adjust the geometry to be a 'wheel like' shape.

The end result of what I'm working with looks something like this.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dip2zg14fl7222quc1cw.png)

To control the vehicle, you'll need to add some simple scripts to your vehicle game object. These scripts will handle things like acceleration, braking, steering, and suspension damping. For now, I've just taken the out of the box sample script from one of Unitys tutorials, and made a slight tweak within the `ApplyLocalPositionToVisuals` method, to force the wheel geomtery to align correctly over the Y axis.  Depending on how you setup your car and wheel geometry, this may or may not be relevant.

```csharp
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class CarController : MonoBehaviour
{
    public List<AxleInfo> axleInfos; // the information about each individual axle
    public float maxMotorTorque; // maximum torque the motor can apply to wheel
    public float maxSteeringAngle; // maximum steer angle the wheel can have

    // finds the corresponding visual wheel
    // correctly applies the transform
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0)
        {
            return;
        }

        Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);
        rotation = rotation * Quaternion.Euler(new Vector3(0, 0, 90));

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }

    public void FixedUpdate()
    {
        float motor = maxMotorTorque * Input.GetAxis("Vertical");
        float steering = maxSteeringAngle * Input.GetAxis("Horizontal");

        foreach (AxleInfo axleInfo in axleInfos)
        {
            if (axleInfo.steering)
            {
                axleInfo.leftWheel.steerAngle = steering;
                axleInfo.rightWheel.steerAngle = steering;
            }
            if (axleInfo.motor)
            {
                axleInfo.leftWheel.motorTorque = motor;
                axleInfo.rightWheel.motorTorque = motor;
            }

            ApplyLocalPositionToVisuals(axleInfo.leftWheel);
            ApplyLocalPositionToVisuals(axleInfo.rightWheel);
        }
        
    }
}

[System.Serializable]
public class AxleInfo
{
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor; // is this wheel attached to motor?
    public bool steering; // does this wheel apply steer angle?
}
```

Add this script onto the main "car_root" gameobject, and viola.  You can hit play, and test out the car model.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xe7ydmdz8gqo2oiu5k2s.gif)

Using Unity to develop a wheel collider with the out of the box tools certainly is a very fast and straight forward process.  A lot of the initial perceived complexity is completely removed with the wheel collider game object, and some simple tunable parameters. However, as anticipated, getting the right balance of mass, center of gravity, friction etc will all take some time and experimentation to get a result with a good driving dynamic feeling to suit the style of game your building.

In my next iteration of learning, I'll continue expanding on tuning and experimenting with these settings and parameters and exploring other possible configurations to yield effects like braking forces, limited slip diffs, front-wheel vs rear-wheel drive and more.