Secret Mystery Project

There’s a lot more to this one – you’ll have to ask me in person if you want to know more!

The short version is that this was to be a free-to-play third-person dark fantasy game, kind of a looter shooter in format, but with the kind of character-driven combat variety you’d normally see in a MOBA. Along with a cofounder, I recruited a team of talented folks willing to join the project contingent upon it receiving funding. Unfortunately, shortly after we set out to fundraise in early 2022, the economy took a turn and the fundraising climate changed pretty dramatically. While we had a great team, we had not collectively built this kind of game before, so it was a tough sell to investors and publishers without a prototype.

After our first round of meetings, I started work on a prototype for the game. Unfortunately, after significant work, we decided that it would take too long to bring the build up to a state that investors would take seriously with the time and resources available.

What I’d like to talk about briefly (and somewhat vaguely) here is the combat design and AI work I did on a prototype for this project.

Combat Design

The goal of the prototype was to prove that we could build a compelling combat loop that achieved a few specific goals:

  • Co-op ready and networked by default
  • Accessible combat, ready for mobile
  • Unusual abilities and combos
  • Passable basic enemy AI

To get point #1, we worked with a technology partner (an indie studio I won’t name – that’s confidential!) who provided us with a networked gameplay scripting library and a basic third-person combat template to work from. Building everything networked was more work, but we wanted the prototype to be co-op ready out of the box.

For point #2, I focused on two easy wins: Auto-aim projectiles, and melee attacks that lock onto a target and close the distance automatically. These are both fairly common in AAA games, but the degree to which they’re implemented is often determined by the design philosophy behind the game. I wanted to try to turn both of them up as high as possible without creating behavior that seemed weird or counterintuitive.

Auto-aim was relatively simple to implement: Cast a cylinder straight out from the player’s look direction, and target the first non-obstructed enemy it intersects with. There were a few catches though: I needed to add “target points” on enemies to ensure projectiles would be aimed roughly where a player would want them, and I need to make sure the HUD was VERY clear about which enemy was currently targeted to prevent surprises.

Lock-on melee attacks were a bit more difficult. Simply moving a character towards a target is easy, but there are a whole bunch of parameters to tweak to make it actually feel good. As you can see from the screenshot below, there were a ton of considerations:

Lots of parameters when dealing with lock-on melee attacks

On top of all of that, the HUD also needs to be clear about when an enemy is in melee range.

Unfortunately, I can’t really get into the ‘unusual abilities and combos’ aspect publicly (because that’s part of the content of the pitch!), but I’m happy to talk about that in a private context.

On the other hand…

Passable Enemy AI

This was, unsurprisingly, the most work and the hardest to get right. While I didn’t have any previous experience actually programming AI myself beyond some basic “move from here to there on the navmesh” in Unity, I’ve watched some GDC talks about enemy AI design and was eager to give it a shot. Specifically, I wanted to use the “open cover” method described in this DOOM 2016 GDC talk:

“Embracing Push Forward Combat in DOOM” – Great GDC talk!

And here’s a debug view of what the implementation looked like in practice:

Debug view for cover checks from potential enemy destinations to the player

Ultimately, I built a system that does the following:

  • At run-time, automatically create a grid of waypoints
  • Check each waypoint to make sure it’s on a valid part of the navmesh and remove if not
  • Enemies, at intervals, get a selection of all surrounding waypoints, check if the player is visible from them and that they are reachable, and then picks one that is closest to the “ideal attack distance” (configurable) away from the player
  • “Claimed” waypoints are removed from the waypoint selection temporarily so other enemies don’t try to occupy the same spot
  • If the player gets “too close” or “too far” (configurable), try to move further away from them to another valid waypoint
  • Repeat

There’s still a lot to work needed to make the AI feel really good, but this is a pretty decent system that keeps enemies attacking from a good vantage point from a safe distance.

That’s all for now! Perhaps later I’ll post a lot more about the project.