Today I worked on creating auto-attack script for characters. This is the script that will allow the characters to do a rotation of attacks based on what class they are set to. For now, the script simply runs a single attack automatically, using a series of floats, integers and a bool to tell the character when they should be attacking. This will allow players to not have to micromanage every aspect of attacking that every character does. Healers will use this script to perform a heal attack on the targeted allies, and damage dealers will use this script to perform attacks aimed towards the boss. This will free the player up to managing character movement on the play field.
The script works by creating a cooldown timer for the attacks, referenced as a public integer. Because it is public, it can be increased or decreased based on the class, role, and level that the character is; which is stored in the PlayerPrefs, and is referenced by a persistent script throughout gameplay. This integer, is then used by the script to tell a float, which is set to -=Time.deltaTime so that it counts down 1 unit-per second in real-time. Once the timer reaches 0 or below, the script runs the attack method and resets the timer based on the referenced integer and the process starts all over again.
When the attack method is run, it lets out a projectile from a designated position on the character, which for now is directly in-front of them. Because the targeting script tells the characters to look at their target automatically, the projectile is launched in the direction of the characters target using an updated script from Extinction Plan; originally called "RocketEngine". This is a script which tells the object the rate at which to move, and in the forward direction. Because the forward of the character is always facing its target, this automatically allowed the projectile to move towards its target location without any jostling. And because the targeting script auto-adjusts as you move the characters around, the projectile will always go in the proper direction.
I chose to use a projectile over a raycast in this case as I wanted to give a chance for the attacks to miss if the enemy is moving and you aren't positioned properly. With a raycast, it would have simply hit automatically. This also allows me to change the size of the attack much easier, as well as the rate at which the attack moves across the play-field. Some of the other abilities may utilize a raycast, but for now the basic principle of gameplay is in-place.
After I had the attack script setup, I had to make sure that damage could be calculated. This meant that the attack had to reach the enemy, collide, and register a set amount of damage on that enemy from the impact. Because I wanted all of the attacks to do different amounts of damage, I decided that creating collider methods from tags was probably out of the question. This process would have involved creating a health script on the enemy which had a reference tag for each of the attacks in the game, telling it if an attack with that specific collider hit what to do. This posed a number of problems. If the attack damage is registered on the enemies collider system, then I would have to create not only a collider reference for each attack, but each attacks level if I wanted damage to scale by character level. I would also have to create tags for each attack and attack level for the abilities to use. I would also have to script the ability for the attack tag to be swapped by the character every time the character levels up. None of this seemed like an efficient way to calculate damage output.
I decided to write a simple "HasHealth" to hold the enemies Health amount in. This script uses the basic principle of creating a void to calculate received damage against the total health left. Written as "public void RecieveDamage(float amt)" this allows another script to reference this method, and to take whatever float amt the referencing script says into account as the amount of damage to be taken. Using a simple Mathf.Clamp I was able to specify (hitpoints - amt, 0 , hitpoints) telling the script that the "current hitpoints - the damage amount, no less than 0, and no more than the amount of hitpoints available" was the range of damage to calculate from an attack. It was then as simple as telling the enemy to run a "Die" method if hitpoints ever went to 0 or below.
From the attack side, I created a script to act when a collision happens, telling it to destroy the attack object, and to look for any scripts within an OverlapSphere that have the script "HasHealth". If a script is found within that overlap, then to use the amount of damage specified in the attack and to run the ReceiveDamage script with the attack damage replacing (float amt). This allows for a multitude of attacks to simply tell the enemy how much damage to take on an individual basis.
So now the characters can perform an attack automatically, and if the attack hits the enemy, tell the enemy how much damage to take. I even made sure to add some status ailments such as burn, and poison to the scripts, so if the "isPoison" flag returns true on the attack, the Receive Damage script will run a "ContractPoison" method which utilizes an invoke repeating to calculate damage over time.
No comments:
Post a Comment