Day 44 — Improvements: enemies destroying powerups + powerup collector
Hey and welcome!
To add a bit more challenge to this let’s introduce some code that will make our standard enemy fire at and destroy powerups if they happen to be in front of them. After that we’ll also have a short one about implementing a powerup collector ability for the player.
First up let’s head over to our powerups script and add in an extra bit of code to our collider:
if (other.tag == "EnemyLaser")
{
Destroy(other.gameObject);
Destroy(this.gameObject);
}
Nice simple bit of code here that destroys the powerup if it happens to come in contact with an enemy laser by accident, however we want the enemy to fire at the powerup on purpose. First we’ll need a reference to the available enemies on screen from within our Powerups script so that we can work out the position of the enemy in relation to the powerup and to also make a call to the FireLaser() method in the enemy script.
if (GameObject.Find("Enemy(Clone)") != null)
{
_enemy = GameObject.Find("Enemy(Clone)").GetComponent<Enemy>();
}else
{
Debug.Log("There are no enemies on screen");
}
We’ll need to add this into our start script, with this when our powerup first spawns in it checks the game scene to see if there are any enemy game objects currently and then stores it in a variable called _enemy. If there aren’t any enemies then I’ve set it to log a message to the console for the time being. Doing this it stops our game from coming up with null reference errors since it can’t always be guaranteed that there will be an enemy object when a powerup first spawns in.
With a reference to the enemy and the enemy script let’s go ahead and make use of that with some code in our Update():
if (_enemy != null)
{
float distance = _enemy.transform.position.x - transform.position.x; if (distance < 0.2f && distance > -0.2f)
{
if (_enemy.transform.position.y > transform.position.y)
{
_enemy.FireLaser();
}
}
}
With this bit of code we’re constantly getting the distance between the distance value of the enemy and powerup x position. When the distance is small it means that both x values are pretty close together, and so long that the y position of the enemy is greater than the player we can call the FireLaser() method to fire at the powerup:
public void FireLaser()
{
StartCoroutine(FireLaserRoutine());
}IEnumerator FireLaserRoutine()
{
_canFire = true;
yield return new WaitForSeconds(0.1f); if (_canFire == true)
{
GameObject enemyLaser = Instantiate(_enemyLaser, transform.position, Quaternion.identity);
Laser[] lasers = enemyLaser.GetComponentsInChildren<Laser>(); for (int i = 0; i < lasers.Length; i++)
{
lasers[i].EnemyLaser();
}
_canFire = false;
}
else
{
Debug.Log("Can't fire");
}
}
This is near identical to our regular laser firing routine but for this one it only runs once.
You’ll notice above that the enemy fires off two shots, that’s because the regular fire laser that the enemy has is also firing off since that Coroutine is always running.
Powerup Collector
Now it’s time to implement a feature where the player holds down the C key and all available powerups on the screen will move towards the player.
private _powerupSpeed
if (Input.GetKey(KeyCode.C))
{
GameObject[] _powerups = GameObject.FindGameObjectsWithTag("Powerup");
Transform[] powerupTransform = new Transform[_powerups.Length]; for (int i = 0; i < _powerups.Length; i++)
{
powerupTransform[i] = _powerups[i].transform;
powerupTransform[i].position = Vector3.MoveTowards(powerupTransform[i].position, transform.position, _powerupSpeed * Time.deltaTime);
}
}
Since we’re looking for a key input we’ll put the above code in the update method. We’ll also be able to create local variables containing the powerup objects using FindGameObjectsWithTag since every powerup shares the same tag. Then with those we can use _powerups.Length to get the number of powerups on screen so that we know how big to make our Transform array that we’re defining on the next line as well as how many times our loop should run.
In the loop itself we assign the powerup’s transform to the transform array we created earlier so that we can get a reference to the powerup’s position and alter it using the MoveTowards class that we’ve seen in use before with the enemy ramming feature.
Works pretty well, handy for making them avoid the path of the enemy now that they have the ability to destroy them.