【Unity】抽象クラスで継承先にメソッドのオーバーライドを強制できる

抽象クラス・抽象メソッド Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「抽象クラスってなに?」

「何のために抽象クラスを使うの?」

というお悩みの方に向けた内容となっています。

Unityで使うC#では、抽象クラス抽象メソッドというものが使われます。

この抽象クラスとは、抽象メソッドを1つ以上持つクラスのことで、継承することを前提としているため、インスタンスを生成しないクラスです。

そして、継承先の派生クラスにおいて、メソッドの具体的な処理を強制的に実装させることができます。

そこで、このページでは、UnityのC#で使うことができる抽象クラス・抽象メソッドについて、どんなクラスなのか、また使い方や作り方までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

抽象クラスとは?

まずは、抽象クラスがどういうものなのかを紹介していきます。

抽象メソッドを1つ以上持つクラスのこと

抽象クラスとは、抽象メソッドを1つ以上持っているクラスのことです。

そもそも抽象メソッドというものは、そのクラスで中身を定義していないメソッドのことを指していて、簡単に言えばメソッドの枠だけが作られているものになります。

この抽象メソッドを持つ抽象クラスというのは、継承することを前提としています。

そして、その継承先である派生クラスにおいて、中身のない抽象メソッドの具体的な処理を定義してあげることになります。

このように、抽象クラス中身の無い抽象メソッドを持つクラスのことで、その継承先のクラスにおいてメソッドの処理内容を定義して使います。

なお、継承については、以下のページでも詳しく解説していますので、参考にしてみてください。

継承先でメソッドのオーバーライドを強制できる

抽象クラス・抽象メソッドを使うメリットとして、継承先でメソッドのオーバーライドを強制できるという点があります。

オーバーライドというのは、派生クラスにおいて、継承元のメソッドの内容を書き換えて、処理を変更することができる仕組みです。

前述の通り、抽象クラスを継承した派生クラスでは、元の抽象メソッドの処理内容を必ず定義してあげる必要があるため、このオーバーライドを強制することができます。

もし、派生クラスで抽象メソッドの処理を定義していない場合は、エラーが発生することになるため、設定ミスを防ぐことができます。

このように、抽象クラスを使うことで、派生クラスでのメソッドのオーバーライドを強制させることができます。

なお、オーバーライドについては、以下のページで解説していますので、そちらも参考にしてみてください。

抽象クラスの作り方・使い方

ここからは、抽象クラスの作り方や使い方について紹介していきます。

abstractを付けて抽象クラスを作る

まず、継承元となる抽象クラス・抽象メソッドを作っていきます。

public abstract class Test  // 抽象クラスを作る
{
    public abstract void Action();  // 抽象メソッドを定義
}

1行目で「Test」というクラスを定義していて、classの前部分に「abstract」というキーワードを付けることで、抽象クラスとすることができます。

なお、抽象クラスは、継承させることを前提としているため、このabstractを付けることでインスタンスが生成されないようになります。

また、3行目で中身の無い「Action」というメソッドを定義していて、同じくメソッド名の前で「abstract」を付けておくことで、抽象メソッドとすることができます。

ちなみに、抽象クラスの中に抽象メソッドが一つでも無い場合は、エラーが発生することになります。

継承先でoverrideを付けてメソッドの処理を作る

抽象クラスと抽象メソッドが作れたら、継承先のクラスで「override」というキーワードを付けてメソッドの処理を記述していきます。

using UnityEngine;

public class TestA : Test   // 抽象クラスを継承する
{
    public override void Action()   // 抽象メソッドの中身を定義する
    {
        Debug.Log("アクション");
    }
}

先ほどの「Test」という抽象クラスを、3行目で継承するように記述しています。

そして、「Action」という抽象メソッドを、5行目でoverrideのキーワードとともに定義していて、中に行いたい処理内容を記述しています。

これでこのクラスにおいて、Actionのメソッドを呼び出すと、中に記述した処理を行うことができます。

なお、抽象メソッドの内容を定義していない場合は、エラーが発生します。

敵のクラス毎に別の攻撃処理を作る

実際に、Unity上で抽象クラスと抽象メソッドを使って、敵ごとに異なる攻撃処理を作ってみます。

まず、継承元となる「Enemy」という抽象クラスを以下のように作っていきます。

using UnityEngine;

public abstract class Enemy : MonoBehaviour // 抽象クラスを作る
{
    public abstract void Attack();  // 抽象メソッドを作る

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);    // マウスカーソルの位置から奥に進むRay
            RaycastHit2D hit = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction);  // Rayに当たったオブジェクトを格納
            
            // 当たったオブジェクトが自身のオブジェクトの場合
            if (hit && hit.collider.gameObject == gameObject)
            {
                Attack();   // メソッドを呼び出す
            }
        }
    }
}

3行目で「abstract」を付けてクラスを定義することで、抽象クラスとしています。

そして、5行目で「Attack」という攻撃処理用のメソッドを作成していて、同様に「abstract」を付けて抽象メソッドにしています。

また、このAttackのメソッドは、それぞれの敵オブジェクトをマウスでクリックした場合に処理が行われるようにしたいので、Raycastメソッドを使ってオブジェクトがクリック判定された際の17行目で、Attackメソッドを呼び出すようにしています。

次に、以下の3つのオブジェクトをコライダーコンポーネントを紐づけて配置しておきます。

そして、それぞれのオブジェクトにスクリプトをアタッチしていきます。

using UnityEngine;

public class EnemyA : Enemy // 抽象クラスを継承
{
    public override void Attack()   // 抽象メソッドの処理を定義
    {
        Debug.Log("突き刺した!");
    }
}
using UnityEngine;

public class EnemyB : Enemy // 抽象クラスを継承
{
    public override void Attack()   // 抽象メソッドの処理を定義
    {
        Debug.Log("火を吐いた!");
    }
}
using UnityEngine;

public class EnemyC : Enemy // 抽象クラスを継承
{
    public override void Attack()   // 抽象メソッドの処理を定義
    {
        Debug.Log("噛みついた!");
    }
}

3行目で「Enemy」のクラスを継承するように記述しています。

また、5行目で「Attack」のメソッドを「override」を付けて定義していて、それぞれのクラスごとに処理内容を変更して記述しています。

これでゲームを実行してみると、

オブジェクトをクリックするとAttackによる攻撃処理が行われますが、それぞれのオブジェクトによって処理を変更することができているのが分かります。

まとめ

このページでは、UnityのC#で使うことができる抽象クラスと抽象メソッドについて、どういうものなのか、また作り方や使い方までをまとめていきましたが、いかがでしたでしょうか?

抽象クラスとは、1つ以上の中身を持たない抽象メソッドを持つクラスのことで、継承させることを前提としているクラスです。

この抽象クラスを使うことで、継承先のクラスで抽象メソッドの中身をオーバーライドさせることを強制できる、というメリットがあります。

抽象クラスと抽象メソッドを作る際は、abstractキーワードを付けて定義し、継承先ではoverrideで抽象メソッドの処理内容を書き換えて使うことができます。

最後までお読みいただきまして、ありがとうございました!

コメント