Speeder Drift

A small arcade style racing game. Race against five AI opponents, drift, crash, and rocket your way through the winding race track to see if you can come in first place.

Interesting Problems

For this project, the racing controls and physics-driven mechanics where pretty simple to implement, but some of the secondary features required interesting solutions.

Racer AI

I needed a simple way to have AI driving opponents race around the track. They needed to seem smart, and the racers had to drive differently in order to avoid driving in a neat single file line. A dynamic AI that could automatically figure out how to drive any track I threw at it would be cool, but I wasn’t sure I wanted to do something that complicated for this small single-track game. So I developed a way to manually mark up the track to give the AI guidance.

I made a series of racing nodes. Each node had a position, a trigger line, and a reference to the next node on the track. At the start of the race, I pass the location of the first racing node to the AI racers. The racers turn their speeder until it is pointing in the direction of the node and then boost forward. When the AI speeder hits the node’s trigger line, the AI is given the next racing node in the chain. With nodes set at the proper points along the track, the AI can drive it successfully.

To make sure the AI didn’t drive the track in exactly the same way every time, I added a little randomness. When the AI heads toward a racing node, it actually heads toward a random point within a given distance from the node. This allows variation in driving and I can also change the driving skill of each opponent by giving them larger or smaller random range.

the blue dots are the racing nodes, the thin green lines are the trigger lines.

Who’s in First?

Determining who wins the race is easy—you just see who hits the finish line first. But to calculate what place you are in at any given time turns out to be a lot more complicated.

The solution I landed on was to trace a line across the center of the entire track to use as a “measuring stick.” I used Bézier Path Creator from Sebastian Lague. Once I had the line, I could calculate what the closest point on the line was from any given speeder position. After that, I compared the positions on the line between all the racers and ranked them by who was the farthest along. This works quite well as a solution. The only point where it sometimes glitches for a moment is during the loop where the line crosses itself.

The Loop

Having one part of the 2D track going over another part was a little tricky. In retrospect the easy way to do it would be to make the race track with 3D depth and then literally have the bridge above the ground. However, when I was working on this, I was deep in the 2D mindset, so I came up with a different solution.

I used Unity Layers to mark which objects were above or below the bridge. When a speeder approached the bridge, it would hit a collider that would change its layer. This would in turn affect which items it could collide with and which order the items were rendered in. All that created the illusion of racers being above or below the bridge, but in actuality, all the racers are driving through each other.

This was a fun solution but it is not as flexible as using the Z axis.