Adding a new ability to our prototype — The Triple Shot
The first thing we are going to do is add a laser prefab to our Hierarchy window.
We want our 3 lasers to appear at precise locations of our ship when we fire the triple shot.
To do this, let’s set our player game object position to 0,0,0.
Note the original player position for later is 0, -3.16, 0.
Once we have moved our laser into each of the desired positions, noting the correct position, we can move onto coding.
I came up with the following:
The first will remain the same as our normal laser, and the additional 2 lasers have a pronounced x and y offset from the original laser.
Note, you want the Y value for each of the 2 lasers to be the same for conformity and visual appeal.
Powerup game logic
Before we can implement our new triple shot ability, we need to have a good idea of the intended implementation.
In our prototype, we’ll use the tried and true, battle-tested approach of spawning a sprite on the player screen that the player can collide with, thus picking up the powerup.
We’ll use this implementation for our triple shot.
Adding triple shot code to the Player script
The first thing we want to add to our Player script to implement our triple shot code is a variable.
We’ll need a true/false variable, a Boolean, so our code can track when the tripleshot is active and when it is not.
By default we set it to false.
We need to update our FireLaser() method to fire the triple shot when it is active.
A simple if statement and some instantiate statements based on the positions we’ve noted leaves us with the above.
For the moment, the fire rate remains the same for either the triple shot or normal shooting.
Timing is everything
To me, the current cooldown for the normal laser used on the triple shot feels like too much screen clutter.
I want to slow this down, so we will need to modify our FireLaser() method to take into account different cooldowns.
After playing around with the fire rate, I settled on 0.35f for my triple shot cooldown rate compared to the normal 0.2f firing cooldown.
To implement this, we need to add a new variable for the triple shot cooldown.
We then modify our FireLaser() method so that the cooldown is no longer outside of the if statement, thus shared by all firing types, but rather in the if statement and using the associated cooldown variable.
We can test this out by simply setting our _tripleShotActive variable to true.
Once you’re done with that, return it to a false value.
Adding the powerup
Using a sprite of your choice, add it to the Hierarchy window.
This sprite will represent the triple shot power up the player can collect by flying into.
I’ll be using the sprites provided by GameDevHQ.
Add the Collider
For this powerup to register collisions, it will need a collider.
We’ll add a Circle Collider 2D component to the Triple_Shot_Powerup game object.
Remember to set “Is Trigger” to true by clicking the checkbox.
Next we need to add a rigidbody and make sure to set the Gravity Scale to 0.
Create the Powerup script
We’ll create a new script and add it to our Triple_Shot_Powerup game object.
Coding our Powerup Script
We are drawing heavily from our enemy script since the behavior is very similar.
Spawn above the screen, move down, and destroy once off screen.
We’ve set our speed to be a bit slower, 3 rather than the 4 in our enemy script and we don’t respawn the powerup at the top of the screen once it reaches the bottom of the screen.
We generate random x positioning for the spawn in our Start() method, however we don’t need the same in our Update() method like we did with our Enemy script so it has been removed.
On collision event
We aren’t interested in any collisions other than the player, so we use a very simple if statement checking the tag of the object this game object collides with in the OnTriggerEnter2D() method.
Modifying our Player script
We need to be able to tell the player script to switch to triple shot firing mode once this object collides with the player.
To do so, we add a simple method to our player script to set the value of our _tripleShotActive variable to true.
I’ve placed it beneath the Stunned() method in the player script.
Back in our Powerup script, we modify our OnTriggerEnter2D() method. I’ve renamed the argument it takes to other and added the if statement to check for the Player tag on other.
If the other game object is the Player game object, we get the player script on that game object and call the TripleShotActive() method which will activate the triple shot on our player script.
We also want to destroy this object on contact with the player game object.
Save both the player and powerup scripts, and run the game in Unity.
Make sure you have a Triple_Shot_Powerup prefab in the hierarchy for testing purposes.
You should be in single fire mode until you touch the powerup, at which point the player will switch to triple shot firing mode.
We have to decide how we want our powerup mechanic to work.
Do we want this to be a permanent buff?
If so, leaving our active variable as true is not a problem.
Do we want it to last for a certain amount of time?
If so, we need to add some duration conditional logic to our code.
Its your game, so its your decision.
For the purposes of this tutorial, we will go the extra mile.
Create the triple shot powerup prefab
Before we forget though, let’s drag our Triple_Shot_Powerup game object from the hierarchy window down to the prefab folder in our Project window.
Now we can delete the Triple_Shot_Powerup from the hierarchy when we are ready without losing our work.
Since we don’t want to be raining powerups at the beginning of every game, eventually we will have to implement the game logic that spawns this powerup at a random or pre-determined times.
Return of the coroutine
We’ll modify our player script, including our TripleShotActive() method with a StartCoroutine call to a new method, TripleShotPowerDown() as shown above.
This will keep our triple shot active for 5 seconds before returning to normal fire.
If we save our scripts in visual studio and run the game with the triple shot powerup prefab back in our hierarchy window, we can test if our cooldown is working.
Now, back in our Powerup script, we’ll add a null check for the player component just to be safe.
Animate the sprite
If you have chosen an animated sprite for your powerup, it may differ from what I have here.
However, we are going to implement the sprite animation based on several different sprites in our example.
The Unity Animation Window
First, let’s create an animations folder in our assets folder.
Now, we’re going to open the animation window and dock it as shown above.
We’ll click on the “Create” button in our new animation window.
Proceed as shown above. When you are done, you should see the following in your Project folder window.
We’ll hit the record button in our Animation window, select all of our sprites using the shift key, then drag and drop them into the animation window.
We now have a basic working animation as we can see in the scene view above when we hit play.
Now, while we added our animations, Unity went ahead and added an Animator component and animation controller to our Triple_Shot_Powerup game object.
Let’s remember to save this to the prefab by clicking overrides and apply all.
By clicking on the animation controller either in the Inspector of our prefab or in the project view, we Open Unity’s Animator controller window for this particular controller.
Spawning the powerup using our Spawn Manager prefab
Let’s add another empty container to our Spawn Manager game object in the Hierarchy window using Create Empty.
We’ll call it “Powerups”.
Open the SpawnManager script.
Add the 2 variables shown above, _powerupsContainer and _powerupTripleShotGO.
In Unity, with the SpawnManager game object in the Hierarchy view selected, we want to drag our new Powerups container to the Powerups Container field in the inspector.
Then drag the Triple_Shot_Powerup prefab from the prefabs folder in the project view into the inspector as shown above.
Back in Visual Studio, we have more work to do with our SpawnManager script.
I’ve renamed “_enemySpawnPosition” to “_defaultSpawnPosition” and updated the variable name where used.
This variable is use just to initially spawn game objects above the player screen out of view.
Since each gameobject than randomizes it’s location before appearing on screen, we can use this variable for both enemies and powerups.
Add another IEnumerator method
As shown above, we add a “SpawnPowerupRoutine()” method to the class based on our existing “SpawnEnemyRoutine()” method.
We make some modifications though, instead of passing one variable for “spawnInterval”, we pass in two.
This let’s us randomize the powerup spawn for some variation.
We may implement this for the enemy class as well if we desire to.
That’s it, try it out!
Next time we’ll add a speed boost!