Brynn Edwards' Portfolio Site
  • Home
  • Projects
  • Code Samples
  • Contact

​Phantom of the Masquerade

Gameplay & Game AI Programmer
Phantom of the Masquerade is a small Unity project made for the 2026 Global Game Jam. The core gameplay is similar to games like Where's Waldo where you must find a character with a specific appearance. Notably, while you are looking for them, all the characters are moving around the masquerade.
My role as Game AI programmer was to get around 100 agents wandering randomly around a ballroom in 48 hours. Our initial plan was to have them dancing, drinking, or mingling with each other in different locations, and I designed the framework around making this implementation as easy as possible. Unfortunately, all the unique actions were cut due to our art 'budget'.
The first hurdle to getting 100 agents to navigate a ballroom is to get a single agent to navigate from point A to point B. I elected to use Unity Navigation for the sake of time, as there's no need to rewrite an A* algorithm for a 48 hour Game Jam. This did run into an issue with being a 2D game, as Unity Navigation is built for 3D games.  Instead of using the official built-in package, I had to utilize NavMeshPlus, which expands the default navigation to allow for 2D pathfinding.

Full Playthrough

Play Now
In order to allow for different behaviors for mingling, dancing, and drinking, I initially thought to use a Behavior Tree. This caused problems when trying to get it to work with navigation because, again, Unity's built-in packages were made for a 3D game, and the logic to determine when the task had finished ignored the y-value of the target. While this isn't a huge issue for 3D games (unless they have a very vertical level) it breaks navigation entirely for 2D games. In the end, I rewrote the navigation leaf node with slight changes in order to get it working with 2D. Which was the last step to get a single agent navigating correctly.
Picture
Next up was testing it with multiple agents. I had some code that allowed them to find and reserve a preset location, so all I had to do in theory was add more locations and more agents. Scaling up the number of agents revealed an immediate issue, they were getting stuck on each other very easily, notably at chokepoints. An ideal solution for this would've been to write up a custom avoidance behavior to allow navigating around each other instead of the default behavior which attempted to navigate away from each other. However, for the sake of time, I decided it'd be quicker to fiddle with some settings so that there'd be less agents moving through more space. This increased throughput made the problem of them getting stuck on each other a lot better, though it did persist at an acceptable level even into the final build.
At this point I had a first pass of the AI, and I realized that behavior trees wouldn't be the best design pattern to use here. The difference between each action in our game would likely be something simple like a small animation. I realized it would be more effective to use a Smart Objects pattern, given that we needed locations for each agent to navigate to anyway. It'd be fairly trivial to give them the animation info and tell each agent to do whatever the location says.  It'd also allow for an incredibly scalable system, even if we did only have two or three different actions planned. I did implement a base smart object, although again, the individual actions ended up being cut because unique animations required time that we simply didn't have.
I spent the rest of the Game Jam implementing the Game AI into the actual levels, which was fairly trivial, and making small tweaks to navigation to get them stuck on each other slightly less.
A quick retrospective here, but using a Behavior Tree was incredibly overkill for this project. The decision to swap to Smart Objects made the behavior pretty much useless outside of finding, reserving, and moving to each location. I don't entirely regret using it though, as I got some pretty valuable experience with common Game AI Design patterns and got a unique insight into Unity's implementation of a Behavior Tree, which has some interesting differences with the other implementations I have worked with. Namely the lack of decorators, and an expanded control node category.
Proudly powered by Weebly
  • Home
  • Projects
  • Code Samples
  • Contact