In this Design Blog, I will be showing the process of breaking down overheating weapons, a commonly used part of the Covenant’s arsenal in the Halo franchise, into the core mechanics and using that to design and implement this in Unreal Engine 4.
How these weapons work in Halo
Overheating Weapons, such as the Plasma Rifle, make use of a heat gauge that appears alongside the ammo count, unlike their reloading counterparts such as the Needler, the total amount of shots for weapons like the Plasma Rifle is the entire weapon magazine, or battery percentage, and the number of bullets in a magazine for reloading weapons is replaced by a bar representing how hot the weapon is before it will overheat.
When the heat gauge becomes full, the weapon is considered as overheating, playing an animation showing the gun cooling down. and the heat gauge in the HUD starts to go down. During this time, the player cannot fire the weapon until both the animation has finished playing and the heat gauge in the HUD is empty, however, if the weapon is fired but doesn’t overheat, the weapon’s heat gauge instantly cools down at a rapid speed.
Due to the nature of these weapons, each shot is the equivalent to 0.5% of the weapon’s battery, meaning that unlike reloading guns, simply stepping over an overheating weapon won’t recharge the weapon’s battery, instead, the player has to replace the weapon with another with a higher amount of battery left.
So in short, these were the mechanics I needed to replicate for this case study:
- A fixed number of available shots, possible done as an Ammo integer, that cannot be topped up
- A dynamic heat value that increases when the gun is fired and decreases when the gun is not firing
- A fixed value that determines maximum heat
- A true/false value to determine whether or not the weapon is overheating
Remaking the Original Plasma Rifle
Summary of Implementation
Because this prototype focussed on the creation of certain types of weapons from a franchise of the FPS-genre, I decided to start with the first-person template for Unreal Engine 4 as the foundation for this prototype. Since the template puts the player and the weapon together in one object, I immediately separated the gun and player into their own objects, making sure that they are initialised and set as the player’s equipped weapon or the player themselves so the player and gun parent objects could access each other.
This allowed for one object to serve as a parent for every gun, meaning core gun logic could be placed in the parent while children could be edited to meet the needs of the individual gun, to be more flexible with designing and balancing weapons as well as allowing additional mechanics such as switching between weapons and/or picking up new weapons on the ground.
It’s worth noting that I had used a lot of variables to prevent hard-coding any behaviours and allowing easy customisation of lots of different objects, making designing and tuning weapons a much easier process.
- Ammo (Integer) – Amount of shots that can be fired, gets decremented when being fired.
- IsFiring (Boolean) – Sets to true while the player is holding down the Fire Weapon button, later changed for the purpose of non-automatic firing to prevent the player from rapidly spamming bullets
- IsOverheated (Boolean) – Puts the weapon in an Overheating state when set to true
- IsTracing (Boolean) – A setting that decides whether the weapon fires projectiles (false) or uses line tracing (true)
- Fire Rate (Float) – The number of seconds between each shot being fired (1.0 = 1 second). This is involved in all heating and cooling calculations, being multiplied by the heat multiplier, cooldown rate or the cooldown rate multiplied by the cooldown multiplier.
- Current Heat (Float) – The level of heat in the gun, clamped to be a value between 0 and 1.
- Heat Multiplier (Float) – Is multiplied by the Fire Rate to get the result to add to the Current Heat
- Cooldown Rate (Float) – Is multiplied by the Fire Rate to get the result to subtract from the Current Heat when cooling down the weapon outside of the Overheating state
- Cooldown Multiplier (Float) – Is multiplied by the Cooldown Rate which creates a slower cooldown for when the weapon is in the Overheating state.
Projectiles and Line Tracing
The intention of setting up both projectile-based weapons and line tracing was to work out which system achieves the best results, especially when it comes to testing. This is because the original Plasma Rifle in Halo appears to show projectiles being fired out of the weapon but I had an interest to see if using line tracing would make improvements to the original gameplay or if preserving the original gameplay was a better idea.
While setting up the guns to be separated from the player object, I decided that I’d create a Boolean value that decided whether or not the gun could be set to using projectiles, just like the default option created by Epic in the FPS template, or using line tracing.
For projectile-based weapons, I kept the default blueprint for Projectiles created by Epic Games mostly intact, only adding in the Apply Damage logic to allow the projectile to damage enemies in addition to applying physics effects on objects and causing projectiles to get destroyed on contact with any object, regardless of whether they simulate physics. Furthermore, I made some changes to the scale and velocity of the projectiles to make them appear more like bullets as opposed to the default settings that appeared larger and heavier which were completely inappropriate for the objective of this prototype.
For Line Tracing, I had to make use of a locally stored vector to determine the gun’s direction which was set based on the forward vector of the first-person camera. That same forward vector is also used to get the end of the line trace by multiplying it by the weapon’s range.
Using the LineTraceByChannel function in BluePrint, I was able to make line shots using line trace work exactly the same way as firing a projectile but that meant values such as the amount of damage that the weapon deals had to be attached to the weapon object while the projectiles, being separate objects, had their own damage value, meaning the line tracing system provided a much simpler approach to customising weapons from a design perspective due to everything being on one single object instead of working with two separate objects to fully set up a weapon’s parameters.
Heating Up the Weapon
A function dedicated to heating up the weapon was created to contain the logic for both setting the level of heat that the weapon currently had in addition to triggering the Overheated state if the current heat reached the maximum amount, being if the value of Current Heat reached 1 or above.
As shown in the blueprint function below, the additional heat added the result of the Fire Rate multiplied by the Heat Multiplier to the Current Heat, a float value between 0 and 1, and added the result iteratively to the value of the current heat variable.
Cooling Down the Weapon
Continuing with the heat element, I also needed to have a behaviour for cooling down the weapon. As this is something that happens automatically after the gun has been fired in the original Halo games, it made sense to have the cooldown behaviour take place under a Tick Event. As shown, while the value of Current Heat is above 0, different cooldown effects happen depending on whether or not the weapon is currently in it’s overheating state.
The cooldown behaviour that takes place when the weapon is not overheating is the result of the Current Heat subtracted by the result of the Fire Rate multiplied by the Cooldown Rate. This sum subracts from the weapon’s current heat in an iterative fashion in a similar fashion to the heating up mechanic.
Overheating the weapon is triggered by the heating up function, called in the weapon firing logic, in the parent when the weapon’s heat reaches the maximum amount. As this was intended to be a special type of cooldown which is significantly slower than usual in addition to stopping the player from firing their weapon until the heat level reaches 0, additional scripting was needed. Firstly, there was a new calculation for cooling the weapon down which required an additional multiplication sum of the Cooldown Rate and Cooldown Multiplier
As for firing the weapon, a condition was created that checks if Is Overheated is not true before allowing gun firing logic to happen, meaning when the gun is in an overheating state, the gun will not fire.
Overall, this achieved an effect where the gun has to cool down fully before the player is able fire the gun again as the cooldown behaviour in the Event Tick sets Is Overheating to false when the Current Heat reaches 0.
Because the original weapon made by Epic Games required the player to repetitively press the Fire Button to fire lots of shots, it was not ideal as Halo’s Plasma Rifle is a fully automatic weapon. Because of this, some scripting needed to happen to allow automatic firing of guns.
Firstly, in the parent object, a custom event that causes a Boolean variable to change to true while the Fire Button is being held down and another custom event that changes Is Firing to false when the player isn’t holding down the button.
As this is in the parent, this creates core functionality ready for child objects to make use of to allow easy implementation of any type of firing, whether it be fully automatic or not, removing the restricted firing behaviour created by default.
Following this, the child object for the specific logic and parameters for the Plasma Rifle was created where I did an event override for the Start and Stop Shooting custom events which still called the parent functions. I added logic for firing the weapon as well as starting or stopping a timer that allowed the weapon to be automatically fired while the Fire Weapon button was held down, making every shot timed by the Fire Rate.
Polishing and Optimisation
Following the initial setup of the gameplay mechanics for the Plasma Rifle, I needed to apply some visual polish to the prototype in addition to optimising the Blueprint scripts to make iterating on this prototype, such as when I make different kinds of weapons like the Plasma Pistol, much easier to manage.
Plasma Rifle Asset and Material
Fortunately I managed to find a Plasma Rifle model to use for the purpose of this prototype so I imported it and the related textures into Unreal Engine. Firstly, I had to set up the skeleton for the Plasma Rifle to have sockets for where the player holds the weapon, where the muzzle flash will spawn and where the smoke VFX will spawn.
Following this, I had to create a material to apply to the skeletal mesh which was made a simple job thanks to the creator of the Plasma Rifle model naming the different types of textures (i.e normals, metallic, etc.) appropriately, meaning I linked the appropriate textures to the correct nodes in the material, resulting in a very nice looking Plasma Rifle for the player to carry in the game.
Dynamic Cooldown VFX
For further visual polish, I decided that a cooldown VFX that had a dynamic length would be a much better idea than the cooldown VFX only appearing when the weapon was overheating to add some additional realism to the idea of using a heat-based weapon.
To achieve this, the cooldown FX custom event was called alongside the newly optimised cooldown behaviour. The VFX would start playing at the end of the firing logic and would not end until the weapon’s heat was at 0 but if the weapon ended up overheating, some SFX would play alongside the VFX.
Optimising Weapon Cooldown
During the initial build, the automatic weapon cooldown used the Tick Event, meaning it was being called every frame which could potentially lead to problems with frame rate and so on during further development of this prototype.
To resolve this, I created a custom event that is called at the end of the weapon’s firing logic to start the process of cooling down the weapon using a timer instead of being called every frame. While the new logic appeared less smooth in the prototype, it was better optimised and still functioned as intended.
Changing Gun Initialisation for the Player
Something from the initial set up for the player that was difficult to work with was the use of a Child Actor component that made a Gun object that considered the player character as a parent.
As there are plans to allow the player to swap weapons (appearing in next month’s blog), making the gun objects a child of the player would potentially lead to complications later in development so I changed the weapon attachment to the player using a scene component where the player’s weapon would spawn and attach.
Removing Unnecessary Variables
Firstly, it was spotted in the Line Trace Function that the local Gun Direction Vector variable did not serve much of a purpose other than deciding the direction in which physics-based objects would travel if hit by a line tracing weapon.
Since the Gun Direction would be set to the player’s forward vector, it was decided that it was better to just use the Get Forward Vector Pure Function to determine what direction physics-based objects would move to optimise the line tracing functionality, especially since using the forward vector provided the same effect as the local variable that was previously used.
Beyond this, the IsFiring dynamic Boolean variable was repurposed for the implementation of non-automatic firing in the Gun Parent object as shown below but it was not serving a purpose to achieve the intended automatic firing behaviour, especially heading into the complete overhaul of automatic firing behaviour.
Automatic Firing Changes
In the initial setup, the automatic firing behaviour was set up in a complicated way due to scripting the parent object and child objects to achieve the automatic firing effect. Because this would become a problem later in development due to the risk of needing to script this logic for every child of the Gun Parent that used automatic firing, I researched into alternative ways to achieve this effect in the parent object in addition to speaking with others in my network about possible solutions.
Using what I found out from my research and networking, I managed to implement a Sequence and Gate combination to achieve an automatic firing effect as shown in the image below. The Delay node was used to achieve both the weapon’s fire rate and preventing an infinite loop error when the player fired the weapon. I also added a condition to only trigger the automatic firing effect if the gun was set to being automatic using an editable variable, meaning it would be possible to decide whether or not to use this new logic by checking a setting in child objects of the Gun Parent. Doing this meant I no longer needed to repeat using the same scripts for every automatic firing weapon.
Making Variants of this Weapon
For the purpose of this prototype, I decided to make two additional weapon variants, one that uses automatic firing but behaved slightly differently to the Plasma Rifle, such as the Brute Plasma Rifle which had a much higher fire rate but overheated quicker, and another that uses non-automatic firing mechanics at its core, like the Plasma Pistol. This was to test how to apply the overheating mechanic in different ways but it was met with a handful of challenges.
To be able to keep the weapon firing accurate to their counterparts in Halo 2, I had to use the weapons in Halo 2 to get a rough guide as to how many shots each kind of weapon would have to fire before it would overheat. In the end, I settled with the following:
- Plasma Rifle: 14 continuous shots before overheating
- Brute Plasma Rifle: 21 continuous shots before overheating
- Plasma Pistol: 16 continuous shots before overheating
The challenge from there was to achieve this as well as an estimated 3 seconds of time for weapon cooldown while overheating based on my experience with the gameplay in Halo 2.
I found myself tweaking with the fire rate, Heat Multiplier, Cooldown Rate and Cooldown Multiplier values of each weapon and doing trial and error until I was happy with the results and placed the final values in a spreadsheet.
What made this a more tedious task than anticipated was likely how the cooldown calculations worked, that being multi-layered multiplication sums just to decide how fast a weapon cools down which put me in a situation where I was doing a lot of guesswork to find the sweet-spot that was as close as I could get to replicating the original mechanics.
What was learned from this?
During the making of this prototype, I developed a much better understanding of inheritance for Blueprint objects, especially when it came to making the core weapon behaviour. While I initially took a complicated approach to creating children of the Gun object, which was later simplified, I learned that by setting up one object with core functionality, I could make lots of different types of weapons and set them differently to create fun and interesting weapons, both developing this prototype further and going into future projects.
I also learned that for creating a more unconventional game mechanic, such as the overheating system done here, I’d unintentionally made some of my functions too complicated, namely the sums for heating up and cooling down the weapon which did multiplications of multiplications to achieve the final result which made tuning the relevant weapons a much more tedious task than it should have been. If I was to do this mechanic from scratch again, I’d certainly look into simplifying the maths involved with heating up and cooling down the guns, making tuning the relevant values and mechanics less tedious when designing the weapons.
Next Month’s Blog
Next month, I will be taking this prototype further by designing and blocking out a level to go with it, more specifically, remaking a part of Halo 2’s campaign by breaking down the chosen level, looking at what would improve that level and not only block out the level but make the improvements that I suggested.
Plasma Rifle – https://halo.fandom.com/wiki/Type-25_Directed_Energy_Rifle
Brute Plasma Rifle – https://halo.fandom.com/wiki/Type-25_Directed_Energy_Rifle/Jiralhanae_variant
Plasma Pistol – https://halo.fandom.com/wiki/Type-25_Directed_Energy_Pistol
Rifle Model – https://skfb.ly/6RCLX
Plasma Pistol Model – https://skfb.ly/6RCM6