Menu
CoddyTech

Abstract Components

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 3 of 64.

Some base classes describe a kind of thing that never exists by itself. Every weapon fires, but a weapon that is neither a pistol nor a shotgun has no way to fire. Mark such a class abstract, and declare each step its subclasses must write as an abstract method, with no body:

public abstract class Weapon : MonoBehaviour
{
    public int shots;

    public void Pull()
    {
        shots++;
        Fire();
    }

    protected abstract void Fire();
}
public class Shotgun : Weapon
{
    public GameObject pelletPrefab;

    protected override void Fire()
    {
        for (int i = -1; i <= 1; i++)
        {
            Instantiate(pelletPrefab, transform.position + transform.right * i * 0.3f, transform.rotation);
        }
    }
}

A subclass that does not write Fire does not compile: CS0534, 'Pistol' does not implement inherited abstract member 'Weapon.Fire()'. Unity also refuses to put an abstract script on an object. Drag Weapon onto one and it says Can't add script behaviour 'Weapon'. The script class can't be abstract!, since Unity could not make a Weapon with no Fire.

Other scripts still work with the base type. GetComponent<Weapon>() returns whatever subclass is on the object, and Pull() runs that subclass's Fire:

// Player.cs
private Weapon weapon;

void Start()
{
    weapon = GetComponent<Weapon>();
}

void Update()
{
    if (Mouse.current.leftButton.wasPressedThisFrame)
    {
        weapon.Pull();
    }
}

Swap the Shotgun component for a Pistol and the Player script stays the same.

challenge icon

Challenge

Easy

Make Monster abstract and let the tower zap every kind.

  1. In Monster, write public abstract class Monster and protected abstract void React();, with no body.
  2. The compiler now points at Imp: add protected override void React() that adds Vector3.forward * 2f to its position.
  3. In Tower, inside the loop, call Zap() on target.GetComponent<Monster>().

Press Play and Space: the slimes shrink, the imp jumps back. Then Check.

Try it yourself

using UnityEngine;

// What every monster shares.
public class Monster : MonoBehaviour
{
    public int hp = 3;

    public void Zap()
    {
        hp--;
        if (hp <= 0)
        {
            Destroy(gameObject);
        }
        else
        {
            React();
        }
    }

    // How this kind of monster reacts to a zap it survives.
    protected virtual void React()
    {
    }
}

All lessons in Game Architecture in Unity

Practice on your own: Unity playground