Menu
CoddyTech

抽象组件

本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 3 课,共 64 课。

有些基类描述的是一种不会单独存在的事物。每种武器都会开火,但既不是手枪也不是霰弹枪的武器无法开火。将这类标记为 abstract,并将子类必须编写的每个步骤声明为抽象方法,不包含方法体:

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);
        }
    }
}

如果子类没有编写 Fire,就无法编译:CS0534,'Pistol' does not implement inherited abstract member 'Weapon.Fire()'。Unity 也不允许将抽象脚本添加到对象上。把 Weapon 拖到对象上时,它会显示 Can't add script behaviour 'Weapon'. The script class can't be abstract!,因为 Unity 无法创建一个没有 Fire 的 Weapon。

其他脚本仍然可以使用基类类型。GetComponent<Weapon>() 会返回对象上实际存在的子类,而 Pull() 会运行该子类的 Fire:

// Player.cs
private Weapon weapon;

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

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

将 Shotgun 组件换成 Pistol,Player 脚本仍然保持不变。

challenge icon

挑战

简单

将 Monster 设为抽象类,让塔攻击每一种怪物。

  1. 在 Monster 中,写出 public abstract class Monster 和 protected abstract void React();,不要添加方法体。
  2. 现在编译器会指出 Imp 有问题:添加 protected override void React(),让它把 Vector3.forward * 2f 加到自身的位置上。
  3. 在 Tower 中的循环里,对 target.GetComponent<Monster>() 调用 Zap()。

按“开始”,再按 Space:史莱姆会缩小,小恶魔会向后跳。然后点击“检查”。

亲手试试

using UnityEngine;

// 所有怪物共有的内容。
public class Monster : MonoBehaviour
{
    public int hp = 3;

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

    // 这种怪物被电击后如果存活,会如何反应。
    protected virtual void React()
    {
    }
}

Unity 游戏架构中的所有课

自己练习: Unity 在线编辑器