Menu
CoddyTech

Abstract Components

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

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

The wizard's tower zaps the monsters in the field. Monster.cs holds what every monster shares: hp (3) and Zap(), which takes 1 hp, destroys the monster at 0 and otherwise calls React(). Slime.cs reacts by shrinking. Imp.cs has no reaction, and Monster hands it an empty React, so nothing tells you it is missing.

  • Make Monster abstract and React an abstract method, so a monster that does not say how it reacts does not compile. The compiler then points at Imp.
  • Write the Imp's React: it jumps 2 units back, away from the tower (along +z).
  • In Tower.cs, when Space is pressed, get the Monster component of each object tagged Monster, whatever kind it is, and Zap() it.

Press Play and zap the monsters, 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()
    {
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Game Architecture in Unity