Day 114 — Making Full use of Class Inheritance in Unity

Connor Fullarton
3 min readJul 7, 2021

--

Hey and welcome!

I’ve got a pretty exciting one for you today. In the last one we went over the code for our MossGiant script and managed to get it working pretty well however it’s not quite perfect yet and we’re still to make full use of inheritance for it.

To give you an idea of what I mean, if you set up the Spider or Skeleton enemy as you have for the Moss Giant you’ll quickly find that the scripts are going to be pretty similar. In fact not just similar but near identical except for the variable names!

Given this, it’s actually more ideal for us to add the code we created into our Enemy script instead and get our different enemy types to inherit instead. Let’s start by checking out what we need in our Enemy script:

[SerializeField]
protected int health;
[SerializeField]
protected int speed;
[SerializeField]
protected int gems;
[SerializeField]
protected Transform pointA, pointB;
protected Vector3 currentTarget;
protected Animator anim;
protected SpriteRenderer sprite;
public virtual void Init()
{
anim = GetComponentInChildren<Animator>();
sprite = GetComponentInChildren<SpriteRenderer>();
}
private void Start()
{
Init();
}
public virtual void Update()
{
if (anim.GetCurrentAnimatorStateInfo(0).IsName("Idle"))
{
return;
}
Movement();
}
public virtual void Movement()
{
if (currentTarget == pointA.position)
{
sprite.flipX = true;
}
else
{
sprite.flipX = false;
}
if (transform.position == pointA.position)
{
currentTarget = pointB.position;
anim.SetTrigger("Idle");
}
else if (transform.position == pointB.position)
{
currentTarget = pointA.position;
anim.SetTrigger("Idle");
}
transform.position = Vector3.MoveTowards(transform.position, currentTarget, speed * Time.deltaTime);
}

Overall it’s pretty similar to what we had in our MossGiant script except this time the currentTarget, anim and sprite variables are protected and we’re also making use of an Init() method to initialize anim and sprite by calling Init() in the Start() method. I’ll show you why we’re doing that in a bit but for now go ahead delete all of the code in your different enemy scripts so that you’re left with something like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MossGiant : Enemy
{
}

Run the game and your enemies should be moving about just as they were before except now they’re all working off of the code inherited from Enemy, how cool is that!

Now before we finish off let’s look into why we’re using an Init() method in our enemy. Simply put we’re doing this so that we can add in unique behaviour to our different enemy types if and when we need to. As an example let’s say we wanted to give our Moss Giant the ability to fly later that depended on a canFly property being true we could do something like this:

public class MossGiant : Enemy
{
public bool canFly = false;
public override void Init()
{
base.Init();
canFly = true;
}
}

As you can say in the above code we’re overriding the Init() method from the Enemy script now an making it our own, if we didn’t include base.Init() we would actually get some reference errors as without this the Init() method from the Enemy script won’t run for our Moss Giant so we wouldn’t be able to get a reference to the animator and sprite renderer. The base keyword is just used to access the parent class that we’re inheriting from, once we do that we can then initialize our canFly property to true which is unique to our Moss Giant.

Now normally we could just create a Start() method here and do it that way instead but the problem of doing that is we could have multiple start methods from our parent and child classes running at the same time so overriding the Init() method in the Enemy script is more optimal here.

If you haven’t done so already add in the Skeleton and Spider into the game using the way you’ve been shown and you should have something like the above. Also make sure that you have this bit in your code for each of your enemies:

public override void Init()
{
base.Init();
}

This will give us the opportunity later to add in unique behaviour for each enemy.

--

--

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