Race Kit Case Study

Brief

Race Kit is a positional tracking system made using Blueprint visual scripting for the Unreal Engine 4 marketplace. As soon as I played with the sample vehicle in UE4, I knew an asset for racing games would be a valuable resource for the incredible UE4 community. I aimed to provide a system that is easy to understand, flexible, accurate, and works with multiplayer.

Race Kit splash
Race Kit promotional image.

Keeping things simple

I knew Race Kit needed to be easy to understand and implement in any project, being valuable as a time saver for experienced users as well as easily accessible for those new to scripting.

The system I designed requires only 3 blueprints users need to implement in their game. A manager actor blueprint placed in the level per race to keep track of the race data and settings, a check point trigger box actor blueprint placed along the race path to understand where the racers are, and a component blueprint to automatically register any pawns participating in the race with the manager.

Race Kit core blueprints
The core blueprints needed for a race.

Sorting positions

The first major challenge was figuring out how the manager object will keep track of racer positions. When the race starts the manager needs to constantly update with current racer information, sorting the array of Race Kit components into their correct placement.

The first step of the solution was to create a blueprint interface that will be used to compare objects. An interface is great because it seperates the logic of comparing objects from the implementation, which is somewhat complex for the race data. The interface inputs the other object and returns an integer, -1 if it's less than the other object, 1 if it's more, and 0 if it's even.

Race Kit compare interface
The compare to interface.

The next step was to create an array sort function. I implemented a sorting algorithm into a blueprint function library so it can be used anywhere in the project. The function takes in an array of objects and returns the sorted array. It utilizes the compare to interface to generically compare objects without the need to know how exactly the objects are compared.

Race Kit sort blueprint
The sorting algorithm made in blueprints. Click to view larger.

Next I implemented the compare to interface in the Race Kit component, comparing Race Kit components by current lap, current checkpoint, or distance to the next check point. Now the Race Kit manager blueprint can call the sort function an array of Race Kit components, placing them in the correct order! Since the sort function is not directly tied to a specific object, it has the added benefit of being able to be implemented with the Race Kit check points as well. Users can add or remove checkpoints and the manager will automatically keep them stored in order.

Race Kit component
The compare to interface implemented on the Race Kit component. Click to view larger.

An accurate race

Some cases are easy to understand for how the manager blueprint will know what positions a racer is in. If they are ahead a lap, or ahead a checkpoint, they're ahead. What about when racers are fighting for position side by side? The system must be accurate and responsive to the current status of the racers down to the millisecond.

I started out by calculating a value on the Race Kit component of the distance between the racer and the check point, but this creates some inaccuracies.

racer distance problem
Issue with using a simple distance calcuation.

This illustration demonstrates the issue with a raw distance value. The B triangle is clearly closer to the red box than the A triangle, but because it's not at the center line of the box it's distance value will be larger, causing it to be placed behind the A triangle.

The solution uses the magic of dot product. In Race Kit, the dot product of the difference between the front point of the racer and difference between the front of the racer and the direction the check point points results in a number that accurately calculates which racer is closest to the check point. Notice how in the following image, even with different vector lengths the dot product is the same. Now, wherever the racer is on the track, the distance to the next check point will be accurate.

Dot product
Dot product visualized from falstad.com

Flexible, expanded use cases

Creating Race Kit using an actor blueprint in the level and an actor component enables a flexible implementation. It means that any type of player pawn can be used with the system, not just vehicles. There's no interference with established game design and be dropped in to any existing game. Race Kit allows for multiple races in a single level. Just as easy as the system can be used in a typical racing game, it can be used in a character controlled action game as a side mission or quest.

Race Kit flying saucer
Race Kit example using a flying saucer.

Finishing touches

The final pieces of creating Race Kit involved making a sample level to demonstrate and explain the functionality. I also created a UI using UMG widgets to demonstrate the placements and data Race Kit can provide.

Race Kit is also set up for multiplayer support using the replication features of Unreal Engine 4. Multiplayer is more important now than ever, and a user of Race Kit can be racing against their friends immediately after implementing the asset.

Race Kit multiplayer
Race Kit example of multiplayer.

Copyright Jay Kesner 2022