If you search online for “how to make a racing game,” you get a bunch of tutorials teaching you one very specific (and very hardcore) way of implementing vehicle/driving mechanics. These tutorials are great if you’re making a realistic driving simulator or racing sim, but chances are they won’t even get you started in the right direction for implementing something that actually fits the constraints of your particular game project.
This article will introduce you to different approaches for implementing racing mechanics, while discussing how these implementation strategies may either complement or clash with your game’s core design.
This approach involves simulating wheels as independent physics objects with their own mass, friction, and suspension. The car is then accelerated by literally having torque applied to the wheels, and as the wheels rotate and collide with the ground, you can trust the physics engine to resolve these forces in such a way that results in the car moving forward. Unity offers a built-in component called WheelCollider, which already offers a friction model to simulate tire slip, as well as a fairly crude suspension system.
One of the drawbacks to implementing racing mechanics in this way is that you need to learn quite a bit about how real-life cars work in order to understand and troubleshoot some of the problems that you’ll inevitably run into with your simulation. For instance, your first attempt at using WheelColliders will probably look something like this:
Even when travelling at surprisingly low speeds, your cars will be highly prone to tipping over unless you simulate the effect of anti-roll bars (basically, if the suspension on one side of an axle is significantly compressed, then you’ll want to artificially compress the suspension on the other side of that axle in order to prevent the vehicle from tilting too far and toppling over). You can also try lowering the center of gravity, reducing the suspension distance, having shorter and wider cars, etc.
Almost every racing game improves car handling by limiting the front wheels’ maximum steering angle based on how fast the car is travelling. For example, at low speeds, you may allow players to steer their wheels by at most ten degrees, but then at high speeds, you may instead limit them to at most two degrees. Dramatic steering angles at high speeds will make your wheels behave more like brakes, thus instantly causing tire slip and clearly not reflecting the player’s intentions. Similarly, it’s also common to vary the acceleration torque based on the current speed, so that you accelerate much faster when you’re coming out of rest than when you’re approaching your max speed.
A physics-based approach unfortunately adds multiple layers of indirection between the variables that you are configuring and the actual result that they have on the screen. For instance, if steering just doesn’t feel right, then it could be a result of any combination of variables, such as mass, engine torque, max speed, suspension values, tire slip values, axle distance, car dimensions, etc. As a result, troubleshooting issues can be frustrating and tedious at times. Sometimes your numbers will be off by an order of a thousand, so it’s helpful to test values on a variety of scales and use real-world values when you can get them.
From a game design point of view, the physics-based approach in general leads to greater complexity, both in terms of mechanics and player skill. A lot of racing games (such as kart racers) just don’t ask players to think about tire traction, balance, momentum, individual bumps in the road, etc., but many of these elements are all baked into the physics-based implementation. Even if you’re not making a racing sim, however, you may still want these elements in your game. They can add a good amount of challenge that keeps players engaged without relying on non-driving mechanics, such as power ups.
However, physics-based implementations tend to add way too much complexity. Pure simulations ask players to understand advanced car handling techniques, and they tend to result in buggy-looking yet “correct” behavior during maneuvers that you may have initially expected to be simple. Unless that’s your intended product, you’ll spend a significant amount of time just trying to “dumb down” your simulation to make it easier to play.
One way to do this is to add autopilot-like features, similar to the many optional “assists” found in most racing sims, which interpret the player’s intentions from their input and then simulates the proper way to drive the car given the current context. If staying true to realism isn’t important for your game, then you can also just “cheat” by applying additional forces to the vehicle and dynamically changing the vehicle’s properties until individual maneuvers become simple to execute.
There are quite a few games that have found a good balance between physics-based interactions and simplistic driving controls, such as Bugbear Entertainment’s FlatOut series or Evolution Studio’s MotorStorm games. As you iterate on your game, it’s important to continuously inspect the individual mechanics and required skill sets that are emerging from your simulation, so that you can decide whether to keep them or to iron them out instead.
For instance, the physics in MotorStorm often makes it easy for cars to lose traction when driving over small bumps in the road. Rather than treating this as something that “just happens,” Evolution Studios seemed to instead choose to expand on it by designing tracks that explicitly called attention to this mechanic, thus challenging players to master it.
You may decide that all of this complexity just isn’t right for your game. You may be working on a project where it just won’t make sense for vehicles to accidentally topple over or bounce around losing traction. If the core of your game is all about simplicity, then a physics-based implementation would most likely be the wrong approach for you. This approach also tends to be a poor fit for games that are explicitly going after unrealistic premises, such as driving on walls, travelling at insanely high speeds, or performing other maneuvers that just bend physics too far.
With a physics-based implementation, you start with your physics simulation and then remove unnecessary complexity. With an arcade-style implementation, you basically start with nothing, and then build individual mechanics until you end up with the right amount of complexity that you’re looking for.
The goal is to build something that feels good for a racing game, not necessarily to build something that’s faithful to how cars actually work. You might start with a single BoxCollider that accelerates by having forces applied when it’s touching the ground. You might then focus on getting steering to feel good, then you might decide that you need either a drifting mechanic or a tire slip system or both. Then you might focus on getting the physics of inclines, ramps, and jumps to feel nice, and then you might build a system to stabilize the car when landing. In general, you’ll most likely follow an iterative and experiment-driven workflow where you end up sculpting a set of mechanics that are tailor-made for your project’s unique requirements.
There’s such a wide variety of potentially valid implementation decisions available here that it really is important to let your projects’ constraints and design goals guide this process. Not every game needs a tire slip mechanic (see Mario Kart), or a drifting mechanic (see Rocket League), or a boost button (see TrackMania), or a throttle for shifting gears (see F-Zero). It’s still important to let your own tastes guide this process as well, because making sure your core mechanics feel good is half the battle for any game project.
For the most part, I prefer to calculate the exact position that the car should be at for every frame, so that I can really nail that “100% traction” feeling. On the other hand, implementations that accelerate and steer vehicles by simply applying forces towards general directions usually just make the car feel like it’s always sliding. That sliding feeling is actually pretty good if the car really does have low traction in that context, but it’s definitely not good when you’re supposed to have strong grip. Manually updating your vehicle’s position every frame might be awkward if you also want to use your physics engine to resolve things like collisions with other cars, so I usually apply the exact force needed to place my vehicle on the correct position by the next frame, while capping those forces depending on the context.
When implementing steering, I really like the approach of calculating the car’s position along a circle based on its current tangent speed. The radius of the circle depends on how far the player is steering using their controller, and if there’s a “drift” button, then the radius is even tighter when pressed. The circle radius also depends on how fast the player is going, so that the player can’t make insanely tight turns while going at high speeds. Furthermore, if the amount of acceleration needed to stay on the circle is too unreasonable (higher than some threshold), then the wheels will go into “sliding” mode, which allows the car to stray away from the circle while leaving skid marks on the track.
It’s surprisingly easy to keep the car from tipping over if it’s only using one big BoxCollider. However, in many cases you’ll want to use either WheelColliders or MeshColliders to handle collisions for each wheel individually, in which case you might be surprised by how easily the car may tilt forward and back while going over ramps or bumpy terrain. In this case, it can be helpful to artificially apply torque to keep the car’s “up” vector aligned with the ground’s normal vector. You can also artificially lower your vehicle’s center of gravity, but keep in mind that that may also make mid-air tricks look a little weird.
You may find that you’ll need to cover up many of these kinds of “hacks” with animations or visual effects that make the game look like it’s more sophisticated. For instance, if your game has no need for a suspension mechanic, then you can at least fake a suspension system by having the car’s visuals lean and bounce, based on the current momentum and acceleration.
Even though I organized these implementation strategies into two buckets (physic-based and arcade-style), the line between the two is definitely a blurry one. It’s not hard to imagine a hybrid model that applies lessons from each side of the spectrum.
Regardless of the approach that you choose to take, it will definitely take a significant amount of work and a lot of iterations to arrive at a polished implementation that consistently feels good to drive.