Enemy AIs, UI logic and Adjusting Weapons Architecture

NavMesh 2D, Changing Weapon's Architecture, and Implementing first UI

For this blog post, I started by cleaning up the weapon system, then gave the enemies some actual AI, and implemented a Pause Menu.

A Cleaner Way to Handle Guns

At first, the weapons were just hardcoded actions. One script, one gun. But that wouldn’t scale, and it was starting to get messy. I was having some other problems as well, specially when grabbing and dropping the gun, because (for some reason), clones of the GameObject were being created instead of using the original. So I decided to restructure it using an abstract class called "GunBase". Every weapon now inherits from it and implements its own "Shoot()" method and other characteristics a weapon has (ammo, icon, audio, etc). For example, the pistol and machine gun now share the same structure but behave differently (semi-auto vs. full-auto). There’s also built-in logic for ammo, bullet speed, and reloading. 


This approach makes it way easier to add new weapons in the future. It also separates logic cleanly between the player and the gun itself. It will let me expand the game without rewriting everything every time. 


Gun Handling and Pickup Logic

On the player side, I added a script called "PlayerGunHandler" that lets the player equip, fire, and drop weapons. Dropping a weapon isn’t just about unparenting it: I had to reset its physics, reactivate its collider, and even add a delay before it becomes pickable again (so you don’t just re-pick it up by mistake). There's also a difference in how the player fires depending on the weapon type, which is handled automatically now. 

This part was EXTREMELY complex and it took me quite some time to get it right, specially the damn "drop and pickup weapon" mechanic. 




Enemy AI: Finally Doing Something

I implemented two types: ranged and melee. Both use the 2D NavMesh system for pathfinding, and both switch states based on what the player is doing.

The ranged enemies stay still until they see the player, then start shooting at regular intervals. If the player breaks line of sight, they’ll start chasing. Melee enemies behave similarly, but they try to get close and punch you instead. It’s a pretty basic state machine (Idle, Chasing, Attacking), but it makes a huge difference in gameplay. 



The trickiest part here was raycasting and making sure the enemies don't shoot through walls. I also had to override some default NavMeshAgent settings since I’m working in 2D. 


I got all of this thanks to this video that explained how to set the NavMesh for 2D projects: 

https://www.youtube.com/watch?v=HRX0pUSucW4&ab_channel=Rootbin

First UI: Pause Menu

I also implemented a proper pause menu. Pressing Start freezes the game, switches the input context to UI, and lets you navigate with a controller or keyboard. The pause canvas gets enabled, and buttons like Resume and Quit become interactable.

You can’t shoot or move while the game is paused, and it even resets input modes when you unpause. The game also defaults to selecting the Resume button automatically so you don’t need a mouse. This part was a bit tricky as well since I had to edit the provided input asset and create a new action map that could work with the arcade machine. 

I still need to implement the "Main Menu" and "Win/Lose" UIs (as well as the winning/losing conditions) but that will be for the next blog post.

Wrapping Up

I’ve reached a point where the game has a solid structure. I can drop in new weapons and enemies easily thanks to some solid prefabs I managed to create. The player seems responsive as well, the pause menu finally does its job, and the input system is clean enough to adapt to the arcade machine.

Next up, I’ll probably focus on visual polish (the TileMap was not sliced properly 😭), create the Main Menu and Winning/Losing UIs and conditions, and fix some last minute bugs. 

Comentarios

Entradas populares de este blog

Core Gameplay Prototype

Final Game and Conclusion