AR RC Car Racing

July 8, 2025

Learnings from developing my first serious AR application over 8 weeks in a team of 4

Project description

Multiplayer, co-located AR racing game allowing players in the same room to compete on custom, environment-aware, procedurally-generated racetracks.

Players can place checkpoints around the real world, and the game will generate a racetrack that passes through all the designated checkpoints, while avoiding real-world obstacles such as tables, chairs, and more (anything recognizable by the Meta Scene API).

We allow unlimited randomized track creation with environmental context, without the tedium of having to manually place every piece of the track. The advantage of this being AR is that players can create racetracks not possible in reality.

Built in a team of 4 over 8 weeks, for Meta Quest 3, @ CSE481v: VR Capstone

See the video demo

ar rc car racing gif

challenges

To summarize the core challenges:

Other challenges faced throughout the process:

also...ar/vr development is such a pain because it takes so long to build to the headset unless you have a very powerful computer...

Research and Planning

The course required us to write out a PRD (product requirements doc) and milestones for each week of the quarter, as well as acceptance criteria for an MVP on week 6 of the quarter. This was a useful guideline/anchor throughout the quarter, although as expected, we overestimated the progress we would be able to make on certain weeks.

After our research, our high-level approach to track generation was to:

Development

Basics:

My main role was in researching and implementing the 3D pathfinding aspect of the racetrack generation.

unity screenshot showing scene mesh

We got stuck on the track generation for 2+ weeks...resulting in a lot of frustrations. Around the time our MVP was due, we spent two days in a row staying in the capstone lab until past midnight trying to make things work.

There was super high latency - depending on the number of checkpoints placed, it could take 20-40 seconds for the track to generate, and the entire headset would freeze during this process. Sometimes, it wasn't able to find a path at all and would infinite loop, despite simple checkpoint placements that should have been pathable. We had conflicting opinions on the viability of our approach - some believed our entire pathfinding approach was overkill, others believed we just needed to find the bug and optimize.

Fortunately for us....it seemed our issue lied in some bug with the implementation from the tutorial. We were querying GPT for optimization suggestions, and one of them was to replace our current SortedSet used in A* search with a custom priority queue, because "it's implemented as a binary search tree and does not handle priority changes efficiently."

It seemed legit, and when we implemented it, the latency of generation went down to like 2 seconds....there was some issue with the way nodes were compared and retrieved from the SortedSet. Still thankful that there was an end to our headaches that didn't involve us starting from scratch LOL

We also had an issue where the first generated track was as expected, but then subsequent generations on the exact same checkpoint configuration led to increasingly warped tracks. This is where I learned that Unity only garbage collects when an object has zero references lol, and we were definitely not cleaning up our previous graphs...

For our MVP, we disregarded co-location entirely. This became our focus after week 6. For co-location, all players need to be able to accurately see a shared racetrack, positions of each others' cars, etc.

We wanted any player to be able to click a "generate" button to create the networked racetrack for everyone. To do so:

things to do differently..

Perhaps we should have started with a simpler pathfinding approach and built off of that? There were some limitations of our approach:

Other things we could have explored first...though these each have their own potential problems too:

The stagnating pathfinding blocked our overall progress for a bit. Better parallelizing our tasks would have improved our efficiency.

Learnings