Protect The Citadel

This project was created in a small group of 4 developers consisting of two programmers, a Producer/3D modeler, and a level designer. The game was created in Unity and is a single player tank survival rouge-like game, where you destroy all opponents and seize the Servers spread around the city while picking up different weapons to defend the citadel with everything you have.
https://cagd.itch.io/protect-the-citadel


PTCEnemyAINavMesh.gif

For this project, I worked as one of the two programmers, coding mainly with enemy AI and working with the other programmer when the enemy interacted with the player or servers. We started out by making paper prototypes and getting the basics for the mechanics of the enemy AI done. Once finished, I moved on to testing out the best way for the enemies to chase and attack the player, as the levels would have buildings and obstacles that could potentially break AI logic. I decided to experiment with the Unity NavMesh feature, where enemy pathing would be calculated to find the most optimal path towards a certain point, while avoiding any walls or buildings that would interfere with the AI.

This is done through Unity's generated field of an objects mesh and factoring other objects height and radius. This generated field is what allows the enemy to move on and any area not allowed by the field does not let the enemy go through, for example a wall. Through experimenting and testing, Unity's feature seemed perfect for our game and we decided that I would take over the enemy AI programming and NavMesh aspect of the project.

PTCEnemyAiRampFix.gif

The next step I took was to refine the enemy behavior once they were in shooting distance. I was tasked to make it so the enemy would stop in place, but the turret on top would rotate around tracking the player and shooting if in range. I knew that once the player was out of range that the enemy would need to readjust their position to chase the player properly, so I added some code that rotated the turret back to its original position and then rotate the whole enemy towards the player to continue chasing them. After refining the enemy AI, it was time to implement the NavMesh into the first iteration of our level and tune up any areas or AI in the level.

When first testing it out, everything mostly worked, but there were a few spots that were not covered and would cause issues if the player went in the unspecified areas on the NavMesh. This was fixed by simply using Unity's NavMesh feature to extend into those areas, however, this lead into another error where the enemies would crash into the sides of ramps and cause their models to be misaligned. The solution I provided at the time was a code that would realign the model if it were to change from a collision of another object. However, if I were to go back, I would make a better fix by adjusting the enemies radius and collider so that the Unity NavMesh would automatically try to avoid those walls more effectively.

PTCMachineGunAI.gif

After fixing the NavMesh and AI issues, we now had access to a system where, hypothetically, any object could be used to chase the player and attack them. With this, I moved on to adding more enemy types to give more variety and challenge to the player when going through the levels or capturing servers. The first enemy type was a machine gun enemy, where the enemy would "rev-up" their turret and then shoot a certain amount of bullets, before needing to reload and repeat the process until the player was out of reach. Using the basic enemy as a base for the new one, I used most of the tracking and NavMesh code while changing the enemy shooting mechanic to have something similar to the intended design. I coded the mechanic to also be ready for future use for the player, so when the play does use the machine gun enemy, it will behave similarly to the enemy's gun, although at the time the task was for the other programmer, so I did not end up polishing up as much as I would have for the player in the end.

PTCEnemyServerAttack.gif

At this point, we had our first playtest and got lots of good feedback about some issues and bugs that would need to be fixed for the next playtest. The bugs involved enemies shooting through walls and enemies shooting from above or below the player. The fixes for these were simple, by making it so that bullets would be destroyed on contact with any other object and I made a function where the enemy compares their Y position to the player's Y position and if they are not within a certain range, they cannot fire at the player; this was to prevent the unfair feeling of enemies being able to shoot vertically but not the player being able to. Once fixed, I moved on to adding a function where the enemy has a random chance to drop an item, a health box or a weapon, when defeated, which went smoothly.

The next big step was adding a function that made some enemies move towards servers instead of the player. The biggest hurdle I had to go over to accomplish this task was making sure that if one enemy is already in a server, then another enemy cannot go towards that server and instead chase the player. This was more challenging than the other due to me needing to access, read, and understand the other programmers code, as they were the ones who worked on the server code and mechanics. However, after communicating with them and clarifying certain parts of their code, implementing checks between the two went smoothly and accomplished the goal very well.

PTCShotgunEnemy.gif

Once adding the new functions and bugs, I moved on to the next task which was another enemy type. The type I worked on next was the Shotgun enemy, where the enemy would need to get closer to the player than the basic enemy and would shoot a blast of spread out bullets. This enemy ended up working very well, as the only major change from the basic enemy was shooting more bullets and at random angles. To make sure these bullets were not too random, experimented with the angles at which would be reasonable for the distance between the player and the enemy, to avoid bullets flying straight up or down. Afterwards, I moved right along to the next and final enemy type, the rail gun enemy. This enemy ended up being a more powerful version of the basic enemy, by increasing their shooting distance, speed of bullets, and power of bullets, these enemies became the strongest enemies to fight. I rebalanced them to not be as strong, as the randomized enemy spawning cause some instances of a large amount of enemy rail guns to appear and kill the player very quickly.

PTCPlayerMachineGun.gif

We were reaching the final sprint of our project and I was tasked to polish some aspects of the enemy, such as visual effects on death, health bar visuals, and testing the NavMesh on all the other levels that were completed. However, halfway through the last sprint, an issue arose where I was then tasked with the implementation of the player weapons and switching, as well as picking up and upgrading the weapons on pick up. Similar to the enemies going towards server task, the biggest problem was navigating through the other programmers code and understanding how and where everything works, except this time around, communication was difficult, thus I was left to dissect it myself. Through many hours, I found out exactly where and how the code for shooting was implemented for the player and took the code from the enemy mechanics and was able to successfully implement similar shooting mechanics of the enemies to the player. Nearing the end, I was also tasked with some player polishing, such as resetting the position if the player fell over, UI fixes with the upgrading of weapons, and a randomized door opening function for the hub, where players would enter to get into the levels that were created. Working down to the very last second, I was able to accomplish all my tasks and get as much as we reasonably could into the game and published to Itch.io.


Working on this project was great experience for working with other programmers in a collaborative way and sharpening my coding skills. I have learned so much during this project, especially with Unity's features and functions that would have made our game impossible if not for it. I am extremely grateful for the opportunity to work on this unique project and thoroughly enjoyed working with the team and producing a game that I can be very proud to have worked on.

Next
Next

Allergy Season