Day 48 — Improvements: boss enemy part 2

Connor Fullarton
4 min readMay 2, 2021

--

Hey and welcome!

It’s time we look into implementing those attacks I talked about in the previous article so let’s get straight into it!

[SerializeField]
private GameObject _enemyLaser;
IEnumerator SpawnAoeLaser()
{
while (true)
{
yield return new WaitForSeconds(8.0f);
if (_enemyCanFire == true)
{
for (int i = 0; i < 9; i++)
{
GameObject enemyLaser = Instantiate(_enemyLaser, transform.position, Quaternion.Euler(0, 0, (i *40)));
}
}
}
}
IEnumerator SpawnFrontLaser()
{
while (true)
{
yield return new WaitForSeconds(3.0f);
if (_enemyCanFire == true)
{
GameObject enemyLaser1 = Instantiate(_enemyLaser, transform.position, Quaternion.Euler(0, 0, 210) * transform.rotation);
GameObject enemyLaser2 = Instantiate(_enemyLaser, transform.position, Quaternion.Euler(0, 0, 180) * transform.rotation);GameObject enemyLaser3 = Instantiate(_enemyLaser, transform.position, Quaternion.Euler(0, 0, 150) * transform.rotation);
}
}
}

In the first coroutine here it’s pretty similar to the multishot code we have for our player but the laser is spawning every 40 degrees around the z axis rather than 20 so that our player has a chance to dodge the AoE attack. We have that set to do the attack every 8 seconds until the boss is destroyed.

In the next coroutine you’ll recognise this code from our enemy that fires lasers backwards but in this case the local euler angles for the z axis have been adjusted so that they’re firing off forwards relative to where the boss object is currently facing.

Make sure to start the coroutines in the Start() method and you should have something like this now:

This is still a bit too easy for a boss for my liking though so let’s ramp it up by adding in some massive lasers that appear on either side of the screen. First create two text objects with a warning message in them that you can place on both sides of the screen and uncheck their active box. With that done add in the code to the UIManager script:

[SerializeField]
private Text _warningTextRight;
[SerializeField]
private Text _warningTextLeft;
public void ShowWarningRight()
{
if (_warningTextRight.gameObject.activeSelf == false)
{
_warningTextRight.gameObject.SetActive(true);
}
else if (_warningTextRight.gameObject.activeSelf == true)
{
_warningTextRight.gameObject.SetActive(false);
}
}
public void ShowWarningLeft()
{
if (_warningTextLeft.gameObject.activeSelf == false)
{
_warningTextLeft.gameObject.SetActive(true);
}
else if (_warningTextLeft.gameObject.activeSelf == true)
{
_warningTextLeft.gameObject.SetActive(false);
}
}

We’re using a new class here called activeSelf. This let’s us check on the current active state of our warning objects, whether they’re true or false/checked or unchecked in the inspector. So what we’re doing in these methods is if the activeSelf is false then we set it to true and if the activeSelf is true we set it to false. Seems a bit counter intuitive here but it will make more sense in the next bit of code coming up.

Before we get to that let’s go ahead and make a large laser object that can take up most of the left or right, I’ve scaled up one of my regular lasers for this.

Make sure to prefab that object as well as we’ll need to instantiate it in the next bit of code here:

[SerializeField]
private GameObject _bossLaser;
IEnumerator BossLaser()
{
while (true)
{
yield return new WaitForSeconds(5.0f);
if (_enemyCanFire == true)
{
_uiManager.ShowWarningRight();
_mainCamera.ShakeCamera();
yield return new WaitForSeconds(2.0f);
_uiManager.ShowWarningRight();
GameObject BossLaserRight = Instantiate(_bossLaser, new Vector3(6f, 0.78f, 0f), Quaternion.identity);
yield return new WaitForSeconds(4.0f);
Destroy(BossLaserRight);
yield return new WaitForSeconds(5.0f);

if (_enemyCanFire == true)
{
_uiManager.ShowWarningLeft();
_mainCamera.ShakeCamera();
yield return new WaitForSeconds(2.0f);
_uiManager.ShowWarningLeft();
GameObject BossLaserLeft = Instantiate(_bossLaser, new Vector3(-6f, 0.78f, 0f), Quaternion.identity);
yield return new WaitForSeconds(4.0f);
Destroy(BossLaserLeft);
}
}
}
}

To start things off we yield the code for 5 seconds before calling our warning text method and our ShakeCamera() method that we use when the player takes damage, it helps to visualise the imminent danger coming. Then we wait two seconds to give the player a bit of time to react and to let the camera shake run its course before we call the warning text method again and Instantiate the laser for 4 seconds before destroying it.

Then we repeat it all but with the laser on the left side of the screen before looping back and beginning it again from the right side of the screen and will keep going until the boss is destroyed. If you give the boss laser the EnemyLaser tag it will damage the player as well. Be sure to remember to start the coroutine with the others and you should have something like this:

There, that should be difficult enough for a boss! I quite like how this boss wave has turned out in the end. With that done though that marks the end of this project, it’s been quite a journey so far and there’s been a good amount I’ve learned over the 48 days so far. It’s time though to move into the 3D world tomorrow as I look into Cinematography with Unity and I hope you can learn a thing or two along the way!

--

--

Connor Fullarton
Connor Fullarton

Written by Connor Fullarton

Hey and welcome! My name is Connor and my goal here is to put out a daily post for a full year about my game development journey.

No responses yet