My objective for this article is to create an enemy type that will fire at the player when it gets behind it.
Before diving into the code work, I made a quick new projectile to be fired by the enemy. CorelDraw has a handy star shape tool that let’s you decide how many points and sections you want in the star. Here is where I ended up.
After bringing this PNG into Unity as a sprite, I give it the Tusk Rotation script. This sprite will be a child object of another parent object so it can rotate freely in local space. I then drag it into the prefabs folder.
I create a new Star Projectile parent object to act as the physical projectile. This new object needs a Rigidbody2D, a CircleCollider2D and the Tusk (shared projectile) script. This new star gets a projectile ID of 3.
The star projectile sprite prefab is now dragged into the parent object to make it a child. I then drag the parent projectile with the attached child into the prefabs folder.
In order for the enemy to fire this new projectile, it will need a reference to it. After saving, the star projectile prefab is assigned to the enemy script in the inspector.
Here in void start, I introduce a local variable called randomSmartEnemy. This rolls a random number between 0 and 5. If the roll is a zero, the enemy gets smart firing capabilities. I am using the regular piranha enemy, so here I also set the color of the sprite to be green. This way the player has a visual reference to know what piranhas will have smart shooting capabilities. I then start a coroutine to control the new firing method for this enemy type.
The smart enemy fire routine method uses a while loop that checks a condition to run. If the enemy is not dead, it can enter the while loop. The local variable offset is used to give my enemy a little additional space visually regarding how far behind the player it is before it start to fire. The next condition checks to see if the player is null (dead), and if the position on the X axis of the enemy is less than that of the player, plus the additional offset. If these conditions are met, the enemy will fire the new star projectile and then wait 5 seconds before moving down the script. This will basically let the enemy fire every 5 seconds so long as it’s alive and behind the player. The final yield statement of 0.5 seconds is what let’s the while loop run every half a second to check the conditions. Without this wait time, the while loop will crash Unity, so that’s super important! A shorter wait time will check the conditions more often, but also create more work for your computer!
All that’s left is the adjustments to the shared projectile script. I have a basic variables for speed, the player, a target transform and a Vector3.
In void start I use GetComponent to grab the Player as well as it’s Transform. This can absolutely be done through one variable with a single GetComponent call. I have other enemy types that only need the Player GameObject, so I figured as long as I am referencing that, I will go ahead and grab it’s transform after. In the final statement, I check to see if the target is null, and if it’s not, the direction variable is assigned. Using the target position and subtracting the enemy position will give a direction that moves the enemy towards the target. Because this is assigned in start rather than update, it will move in a straight line towards the players last known position when it was fired, rather than a homing projectile that updates it’s direction constantly.
The movement method is called in void update. The position of the enemy transform is told to move towards that target direction using the speed variable and delta time so it’s not framerate dependent. The BlowfishSpinesBoundaries method gets called to destroy the projectile when it leaves the screen in any direction.
Here is a clip of the green piranha firing at the enemy as it swims past. I hope to see you in my next article where things get even more difficult for our player. Thanks for reading!