Menu
CoddyTech

敵の基底スクリプト

CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 2/64。

C#では、クラスは別のクラスを継承できます。class Ghost : EnemyはEnemyのすべてのフィールドとメソッドを受け継ぎ、独自のものを追加します。基底クラスでvirtualと指定されたメソッドは、サブクラスでoverrideを使って置き換えられます。また、base.Describe()を呼び出すと、新しいメソッドの中から基底クラスのバージョンを実行できます。通常のC#では、次のようになります。

class Enemy
{
    protected int hp = 3;

    public virtual string Describe()
    {
        return "Enemy with " + hp + " hp";
    }
}

class Ghost : Enemy
{
    public override string Describe()
    {
        return base.Describe() + ", see-through";
    }
}

GhostのDescribe()はEnemy with 3 hp, see-throughを返します。protectedは、Enemyとそのサブクラスがhpを使える一方、ほかのクラスは使えないことを意味します。

Unityでは、敵のコードの大部分を共有できます。ヒットポイント、速度、移動方法などです。このコードはMonoBehaviourを継承する基底クラスに置き、それぞれの種類の敵がそのクラスを継承します。このEnemyはStartでヒットポイントを設定し、Updateで向いている方向へ歩きます。Ghostは開始時の処理を変更し、速度を2倍にします。

public class Enemy : MonoBehaviour
{
    public int maxHp = 3;
    public float speed = 2f;
    protected int hp;

    protected virtual void Start()
    {
        hp = maxHp;
    }

    protected virtual void Update()
    {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}
public class Ghost : Enemy
{
    protected override void Start()
    {
        base.Start();
        speed *= 2f;
    }
}

Ghostはフィールドを継承するため、GhostのInspectorにはmaxHpとspeedが表示されます。また、Updateも継承するので、独自のUpdateがなくても歩きます。hpはprotectedです。Enemyとそのサブクラスは使えますが、ほかのスクリプトは使えません。

Unityはアクセス修飾子にかかわらず、名前でStartとUpdateを見つけ、最も派生したクラスにあるものを呼び出します。EnemyのStartがprivateなvoid Start()で、Ghostが独自のものを宣言した場合、Unityが呼び出すのはGhostのものだけです。EnemyのStartは実行されず、エラーも起きないままhpは0のままになります。基底クラスのメッセージをprotected virtualと宣言すれば、これが通常のC#の仕組みになります。サブクラスではoverrideを書き、base.Start()を呼び出すと、その位置で基底クラスの処理が実行されます。この呼び出しを省略すると、基底クラスの処理はスキップされます。これは、サブクラスが処理を追加するのではなく、ある手順を置き換える方法です。

challenge icon

チャレンジ

簡単

Golem と Wasp が、それぞれの処理の前に Enemy の処理を実行するようにしましょう。

  1. Enemy で、void Start() と void Update() の前に protected virtual を記述します。
  2. Golem で、protected override void Start() にし、最初の行に base.Start(); を記述します。
  3. Wasp で、protected override void Update() にし、最初の行に base.Update(); を記述します。

「プレイ」を押します。ゴーレムは hp が満タンの状態で進み、スズメバチは進みながらジグザグに動きます。その後、「確認」を押します。

自分で試してみよう

using UnityEngine;

// すべてのモンスターに共通するもの。
public class Enemy : MonoBehaviour
{
    public int maxHp = 4;
    public float speed = 1.5f;

    protected int hp;
    protected Vector3 spawnPoint;

    void Start()
    {
        hp = maxHp;
        spawnPoint = transform.position;
    }

    void Update()
    {
        // z軸に沿って城へ進軍する
        transform.position += Vector3.back * speed * Time.deltaTime;
    }
}

Unityのゲームアーキテクチャのすべてのレッスン

自分で練習してみよう: Unityプレイグラウンド