Shotgun Step - An Exercise in Enemy AI

About

Shotgun Step was a project developed by me in Unity/C# to help improve my understanding of Enemy AI in video games.

Fight an AI enemy with a lethal shotgun in narrow hallways. Awareness and good estimation is crucial.

Developing this project has taught me about scalability, game balancing, and how to make AI not unfun by destroying you instantly.

I designed and developed this entire project.

Important Points

  • The Player fights one AI enemy in a close quarters, maze like area. The AI is spawned in a random position
  • Enemy AI checks corners and looks behind occasionally
  • Enemy AI can rush or retreat depending on health and ammo
  • Player’s can throw a bolt/screw (on a cooldown) to generate noise to attract or mislead the AI
  • Point blank shots kill opponents in 1 shot any further range removes half of their health
  • Players have 1 ammo. Reloading takes ~3 seconds and halves movement speed, making the person vulnerable
  • Players and the enemy mostly have the same abilities and limitations (same weapons, max ammo, reloading, health, etc.)

Details

AI Navigation

To get the enemy moving, I quickly learned Unity’s built in navigation, NavMesh. However, the destination of the enemy needs to be determined through my own code. To do this, I have separated the enemy AI into three distinct states.

The first state is Patrol. This is the default starting state. It chooses a random point in a sphere around the origin of the map. It then finds a valid path point closest to the selected random point and assigns that as the destination for which the AI moves towards. When the AI reaches the destination or after a few seconds, it repeats this process again.

The second state is Sound Alert. This is triggered when the player throws a bolt on the ground to simulate sound. When the bolt hits the ground a random point in a small area around the bolt is selected and the AI moves towards it. If the AI sees the bolt then it goes back to the Patrol state.

The third state is Player Contact. This is triggered when the AI sees the player. The AI then waits to shoot until either the player is close enough to kill in one shot or if they are far enough from the player. If the AI is hurt then it will rush the player in an attempt to kill in one shot, since the player only has one ammo. If the AI hits the player for half health then it retreats in an attempt to reload. The AI does not shoot at a medium range (See Gameplay Reasoning).

AI Checks

The AI occasionally looks behind and is able to check corners. For flexibility and simplicity, I have marked the corners found throughout the map. When the AI passes through these corners it checks left, right, forward, and back, but it ignores any direction that is just a wall. It is able to detect walls by periodically putting out a circle of raycasts and determining if the distance of the wall is too close.

Gameplay Reasoning

The game is designed to test a player’s skill of estimation. The player has to estimate where the enemy may be and the range to attack.

According to the rules of the game if you are far when you shoot, you deal half health and have to reload (which is long and slows you down). A player or enemy can abuse this and rush an opponent while they are reloading, I’ve reinforced this idea by adding in a small speed boost when at half health.

The solution is to be able to put enough distance between to be able to reload safely without getting in point blank range hence why the AI does not attack in medium range, and why it reloads and retreats when it fires a far shot.

If the player is not aware enough or ineffectively uses their bolts then they may be surprised at point blank. Don’t worry though the AI has a small delay (approximately the same average human reaction time) before firing.

Biggest Challenges

First biggest challenge I faced was determining how the AI detects corners. I had to break down how people actually perceive corners and tried to apply that to the AI through raycasts. After working that out I realized that it would be too complex especially for the scope of this project so I simplified it down and marked the corner areas. The AI detects if it is in a corner area and then it checks its main directions.

Another big challenge was the game design. I wanted to make the gameplay deeper than just seeing who shoots the fastest so I added in all these other factors to make it a little more complex. Balance was also in consideration, for example, I wanted to make the shotgun shoot multiple pellets, but I feel like it would be too inconsistent (even with a fixed spread) especially in a narrow space. So to simplify it, I made it a slug with damage falloff.