I’ve been toying around with a tiny, twitchy, arcady racing game. Racing games vary a lot; some people want sims with weight traction and simulated drivetrains and others prefer the tight controls of the mario karts.
I started off with a deep dive into car physics. Beckman’s Physics of Racing, Pajecka’s model and Edy’s thoughts on it and the Randomation Vehicle Physics source code were all super helpful. Even though I want something much more predictable and less physical, I got a lot from learning about how a car acts, and then coming up with ways of heavily approximating the feel.
What I’ve found feels awesome:
- Going real fast
- Twitchy and tight: accelerating, braking, changing velocity really suddenly and frequently
- Flipping bumpers/triggers on the controller fast like gear shifting paddles
- Some difficulty of execution: there’s a thrill in watching someone pull off the perfect drifts in mario kart.
This boils down into having a responsive and agile - but predictable - car with a course that rapidly changes. My latest iteration is largely influenced by Space Dust Racing’s video and subsequently a simple raycast vehicle in Unity.
The car started as a cube and box collider, but non-flat surfaces would jolt the car and send it flying. Adding suspension smoothed out the physics (like in life!) and adds a flag if the wheel is grounded.
From each wheel, the car raycasts downward and calculates the distance to the ground if it hits anything. An force is applied upwards from the hit position based on the distance, i.e. how compressed the suspension is.
Immediately, I ran into problems with a super bouncy, oscillating suspension. The IRL and game solution is to dampen the suspension based on the downwards velocity (so the car falling doesn’t all get stored in the suspension, but some energy is dissipated). I had problems with this until I started calculating velocity at the hit position instead of the car body’s velocity. I think this is critical because the car might be rotating (pitching or rolling), causing a difference in velocity at each wheel.
With the raycast suspension, the car body floats above the ground, no longer affected by the builtin drag. I add this back by applying a force proportional to the velocity of the car, projected onto the ground (the car’s local xz plane).
Generally with these physically based karts, you turn the car by applying torque. While this makes the car feel weighty and real (changing direction moves like you’re hauling weight), but the heft makes it pretty unresponsive. I had to turn up the torque super high to make it respond quickly, and then the angular drag through the roof to compensate and stop the car from spinning out.
I’m trying out setting the car rotation based on the analog stick. So far it’s SUPER responsive at twitchy, but definitely a little floaty and more arcade-y than real. Also because the car is no longer being torqued, the wheels apply the drag force at the center of the car, not at the hit point.
The big frustration I’ve had so far is tuning the car. The game boils down into how driving feels, the skill cap and the courses.
I’ve been using
AnimationCurves to make parameters into functions of other parameters.
For example, acceleration lerps from 1 to 0.5 as forward velocity increases, giving a stronger
start. A curve would give me even more control over how acceleration feels. Another case is the
lateral force on the wheel is a curve as a function of angle between the wheel and car velocity. So,
like Pajecka tire models, a wheel turns hard at slight angles, but slips/drifts at more extreme
Unfortunately this means adjusting one aspect means adjusting many parameters, becoming a tedious cycle of adjust, manually test edge cases, adjust, manually test.
Game design problems
Two other challenges I’m facing are motivating drifting and having enough of a skill cap.
Drifting is fun. I want this game to be a drifting game, but I’ve made driving really tight. When you can always turn at max or near-max speed, drifting is strictly slower (there’s still more lateral drag than longitudinal drag on the wheels, so the car goes slower). I’ve had to try to do some subtle things to make drifting faster or turn tighter but it’s hard to make clear why bother drifting if it’s more difficult.
Having really responsive controls also means the car just does what you want. Turns out a car that drives as predictably as Rocket League makes sense for a game where you have to precisely hit a ball at the right angle, but not so much where the game is controlling the car while going fast. I’m still not sure how to keep the car driving so responsive, but also provide room to improve. I think it might come down to course design?