Day 120 — Implementing Behaviour for Different Enemy Types

Hey and welcome!

In this one we’re going to finish off our attack and movement behaviours for our other two enemies. If you remember we have 3 in total, the Moss Giant, Skeleton and the Spider:

Let’s start by looking at the Moss Giant which is actually going to be a copy paste of how our Skeleton functions effectively so I’ll be quick about this one.

Start things off by adding a box collider 2D component to your Moss Giant making sure that it surrounds them and then set their layer to the Enemy layer and then set 50 for the order in layer or to the number that your player and skeleton share.

Next go through the process of slicing the Hit and Attack sprite sheets for the moss giant and then create the animations for both by clicking on the sprite object in your Moss Giant and choose the create animation option in the animation window.

After that it’s just the case of matching what you have in your skeleton animator controller with your moss giant controller.

Now let’s talk code, in our Skeleton class we’re overidding the Movment() method and adding in this code:

public override void Movement()
{
base.Movement();
Vector3 direction = player.transform.localPosition - transform.localPosition;
if (direction.x > 0 && anim.GetBool("InCombat") == true)
{
sprite.flipX = false;
}
else if (direction.x < 0 && anim.GetBool("InCombat") == true)
{
sprite.flipX = true;
}
}

This is the code that let’s our skeleton face the player, we’ll want to add this into our MossGiant class but a much better solution is to add it to the Movement() method in our Enemy class and have and remove this override altogether from the Skeleton so that we’re not repeating unnecessary code!

We do need to make sure that there’s a reference to the Health property and Damage() method we defined in our IDamageable script so overall your MossGiant and Skeleton class should both look like this:

public class MossGiant : Enemy, IDamageable
{
public int Health { get; set; }
public override void Init()
{
base.Init();
Health = base.health;
}
public void Damage()
{
Debug.Log("Moss Giant damaged!");
Health--;
anim.SetTrigger("Hit");
isHit = true;
anim.SetBool("InCombat", true);
if (Health < 1)
{
Destroy(this.gameObject);
}
}
}

The difference between them will be what you output in the Debug.Log() there although it’s not necessary to have. Back in the Unity editor set your moss giant’s health to whichever number you prefer and test it out:

Setting up the Spider

Now let’s have a look at what we’re going to do for the spider which is going to be something a bit more unique as their going to fire off a ranged attack while remaining stationary, in your Spider class go ahead and override the Movement() method so it’s like this:

public override void Movement()
{
}

By not doing base.Movement() this stops the Movement() method from executing for our Spider. Once you’ve done that go ahead and add a box collider around the spider with their layer set to Enemy and the order in layer to match the player and then create the attack animation for the spider:

Edit your Animator for your spider so that it only has an Idle state and an Attack state withtwo transitions going between them both with Exit time enabled.

Next up find the Acid spritesheet in Sprites > Effects and then slice it up. Grab the first sliced image named Acid_0 and drag that into the hierarchy and rename it to Acid. Set the layer to EnemyAttack and the order in layer to 50 and then add a box collider 2D and Rigidbody 2D component. Now head to the animation window and create the animation for this acid effect and then prefab the Acid object.

Create an AcidEffect script to add to your Acid object and fill it with this code:

private void Start()
{
Destroy(this.gameObject, 5.0f);
}
private void Update()
{
transform.Translate(Vector3.right * 3 * Time.deltaTime);
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
IDamageable hit = other.GetComponent<IDamageable>();
if (hit != null)
{
hit.Damage();
Destroy(this.gameObject);
}
}
}

This will make our Acid object move to the right and have the ability to detect collision with the player when it’s Instantiated. Speaking of, let’s go ahead and update our Spider class:

public class Spider : Enemy, IDamageable
{
[SerializeField]
private GameObject _acidEffect;
public int Health { get; set; }
public override void Init()
{
base.Init();
Health = base.health;
}
public override void Update()
{
} public override void Movement()
{
} public void Damage()
{
Health--;
if (Health < 1)
{
Destroy(this.gameObject);
}
}
public void Attack()
{
Instantiate(_acidEffect, transform.position, Quaternion.identity);
}
}

Be sure to add your Acid prefab to the acidEffect variable here through the prefab! This script is set up to destroy the Spider when their health is under 0 and also Instantiate the Acid prefab when the Attack() method is called.

How do we call the Attack() method? I hear you ask. Well, create a SpiderAnimEvent script and attach it to the object that holds your Spider animator, in my case it’s the Sprite object inside the Spider. When you’ve done that add in this code:

public class SpiderAnimEvent : MonoBehaviour
{
private Spider _spider;
private void Start()
{
_spider = transform.parent.GetComponent<Spider>();
}
public void Fire()
{
_spider.Attack();
}
}

This script holds a Fire() method that when called will then call the Attack() method from the Spider class.

Now we’re going to do something pretty cool to call that. Head over to your animation window and open up the attack animation for the Spider. Move over to the frame that you want the Acid to spawn in at and then click the add event option just to the left of your dopesheet:

This will open up a dropdown option in your inspector, click on it and you should see your Fire() method in there.

What we’ve just done here is known as an animation event, it let’s it pick and choose a specific frame of an animation to do a method on from a script. With all that done you should have something like this:

That’s it as far as behaviours for different enemy types go!

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.