top of page
Search

CAGD 470 Group 1, Sprint 6

  • Writer: Els Fouche
    Els Fouche
  • Apr 25
  • 7 min read

Kill Everything As Fast As Possible

Kill Everything As Fast As Possible is a 3D first-person boomer-shooter where you take control of a killer AI hell-bent on destroying every human in sight.


Project Credits:

  • Daniel Bocanegra-Ramos: Lead Designer

  • Jack Bradford: Producer

  • Dylan Brown: 3D Artist

  • Els S. Fouché: Lead Programmer, Level Designer

  • Sean Gibson: Programmer

  • Sophia Villenueve: 2D Artist

  • Rayen Yousfi: 3D Artist


Sprint Summary

This sprint saw the implementation of our final features and significant polish as well as some moderate optimizations. I was able to finalize the aim assist feature that was nearly complete last sprint and implement it into the project along with player-adjustable settings. I was also able to implement a shop system that enables the player to purchases weapons, weapon upgrades, new abilities, and ability upgrades between waves of enemies.


New Features:

  • Aim Assist

  • Weapon & Ability Shop

  • Recoil Animations

  • Time Gain Feedback


Changes:

  • Chainsaw Updates

  • Flesh Cube Improvements

  • Timer Logic Optimization

  • Widget Animation Optimizations


Aim Assist

I was able to finish integrating the aim assist feature into the project during this sprint. The aim assist operates by gathering valid actors within a certain area, sorting them based on a weighted combination of distance to the player and proximity to the center of the screen, and then adjusting a directional vector to point at the targeted foe. This directional vector is then passed into the shooting actor component to determine the directionality of shots. Sorting the actors is computationally expensive and so it is, by default, performed only 10 times per second. This 'precision' value can be adjusted easily and, depending on the actual performance cost of the sort, will likely be improved for the full game release.


Aim Assist

As mentioned, the precision of the aim assist is fairly low. I'll be profiling the game in the coming sprint to check for potential bottlenecks and adjusting the precision accordingly.


Weighted Comb Sort
Weighted Comb Sort

The above code is the primary driver of the aim assist. I was fortunate enough to find examples of a comb sort implemented in blueprints I could model this functionality off of, which I then modified to allow for weighted sorting based on two factors. It sorts actors based both on their distance to some reference location and the angle between them and that reference location.

The Angle Between function uses the dot product of the normalized vectors and the arc cosine function. The angle is taken between the provided forward vector and the position of the target actor after it has been transformed to respect the provided reference location as its origin. Due to the fact that the angle is small when the actor is closer to the center of the screen (presuming that the passed in forward vector is e.g. the camera's), we multiply the weighted distance and the angle. We then compare the values to determine whether the actor moves up the priority list. The actor at the top of the list is targeted.

The multiplication step between the angle and the distance means that if the player is looking at an enemy it is very likely they will be prioritized by the aim assist regardless of their distance, allowing them to 'snipe' distant targets without the aim assist jumping to closer actors. Furthermore, the distance weighting factor can, theoretically, be player-modified to allow for additional customization of the aim assist's functionality.


Aim Assist Settings


Chainsaw Updates

We made a significant change to the chainsaw during this sprint. Previously, the weapon was only able to kill a single enemy. While the chainsaw was active, the player would be locked in place without invulnerability. This forced the player to be selective about when they activated the weapon. Due to the single hit test that was fired when the weapon was activated, the player was also required to be fairly accurate with their positioning in order for the hit to be registered.

This design paradigm that emphasized risk/reward was no longer suitable for the game in its current state, as it now places much more importance on the player maintaining their speed so they don't become overwhelmed by enemies. Thus, the weapon was reconfigured to allow the player to continue moving while it was active and for the weapon to continuously deal damage while active.


Chainsaw Updates

Refactoring the chainsaw code was necessary for these updates. I stripped the code out of our actor component - which I was pleased to do, because it was previously lumped in with the shooting logic and felt out of place - instead moving it to its own actor. This actor was attached as a child to the player. Due to my teammates previous experience with Unity, they had wrapped all of the imported weapons into blueprints, essentially treating them as prefabs. This was a happy accident because it meant that all the weapons were already child actors that were swapped between, which smoothed the chainsaw code refactor.

Chainsaw Actor Filtering
Chainsaw Actor Filtering
Chainsaw Damage Logic
Chainsaw Damage Logic

The actual code is fairly simple. When the actor overlaps with an enemy it checks if it's a valid target by checking the actor's class against a list of valid targets. If it's a valid target, it loads a reference to the actor into a list and notifies the damage logic to run. The damage logic checks the new actor against a list of actors that have already been damaged by the chainsaw during this activation - if the actor is present in this list, it does not damage them again. This is done to prevent the player swiping the chainsaw back and forth rapidly to deal multiple hits to the same target.

The Damage Actors event operates on an array of newly added actors because it is possible, and indeed likely, for the player to hit multiple enemies on the same frame. However, the Damage Actors event should likely be run on the next tick from the Completed pin of the actor filtering loop in order to improve efficiency.


Shops

Towards the end of this sprint I was able to implement the weapon and ability shops into the game.


Weapon Shop


Ability Shop

These shops allow the player to customize their experience with the game, allowing for different ways to approach combat situations. Currently, the costs for abilities are too low and thus allow a player to purchase all of them after wave 1 - this will be adjusted in future builds to create dilemmas for the player.

The shop menus are separated into layers, functional base widgets, and children. Using the weapon shop as an example, we can demonstrate the architecture as a simple hierarchical flow:

  • The base shop layer swaps between the three shops,

    • The weapons layer swaps between each weapon,

      • Each weapon is based on a single parent, and

        • Each child contains the specifics of the weapon e.g. weapon type.

Most buttons are based on a template that is reused throughout the project. This will allow all of the buttons to be updated with sprites and other aesthetic changes simultaneously.


Polish & Optimization

As I mentioned in a previous post, the timer code was contributing to poor game performance due to how it was structured. Additionally, many widget animations were being handled through code rather than the built-in animation utility. There's a simple reason for this: I didn't know about the animation utility. After learning about it, I was able to go back through the timer and deprecate a fairly large amount of code and on-tick operations.


Deprecated Timer Animation Code
Deprecated Timer Animation Code

Furthermore, I was able to refactor the parts of the game state that were meant to handle this code, reducing its complexity. Finally regarding the timer, it now calculates the players remaining time every second rather than continuously. The displayed time is updated every frame using interpolation instead of reflecting the actual time. This combined with the widget changes moderately improved game performance. The timer does calculate the player's actual remaining time when entering a shop in order to prevent stealing from or adding time to the countdown.

Regarding polish, as seen in videos above there's now feedback for the amount of time gained when the player kills an enemy. This time gain popup allows for gained time to stack additively if the player kills enemies rapidly, acting as a sort of 'kill streak' element.


Recoil Curve Table
Recoil Curve Table

During this sprint I also added recoil animations to the weapons when they're fired. These recoil animations are adjusted using the above curve table, allowing the designer to easily fine-tune them. Currently, the general recoil animations are handled via code. A point of improvement would be to use Unreal's animation tools for the recoil but, unlike with the widget animation utility, I'm not sure how to use them yet despite knowing about them.

Due to the fact that the animations are handled in code, several 'fun' bugs were introduced this sprint that needed to be squashed. For example, switching weapons while a weapon was in the recoil animation would continue using the first weapon's anim. This isn't a huge concern, except that not all weapons were imported with the same pivots! This caused the corrective offset to become briefly desynced and resulted in the switched-to weapon being at an odd angle and gradually rotating into the correct orientation. This is fixed...for now - it was corrected with an emphasis on speed rather than robustness. It remains to be seen if it will withstand a pressure test but early indications are positive.

I'd like to give a brief mention to smaller elements of polish. Namely, the 'wave complete,' next wave start countdown, and 'Flesh Cube' animations. The first two make the game feel much more complete; I'm quite happy with them. The 'Flesh Cube,' meanwhile, I simply find funny.


Flesh Cube Animation


Summary

Almost done! This project has been refreshingly simplistic and, so far, I'm quite happy with how it's turning out. I'm excited to get final assets into the game so we can dial in the mood - this final sprint I'm hoping we'll be able to transform the game into a fully complete experience!


Previous Posts

 
 
 

Comments


© 2025 Els Fouché née Rodger Fouche. All Rights Reserved.

Thanks for stoppin' by.

bottom of page