UnityでのGetComponentとポリモーフィズムを利用した Animal サンプル

1. 概要

本資料では、Unity において抽象クラス Animal を基底に、具体的な実装として Dog クラスおよび Cat クラスを作成します。GameObject にアタッチされたコンポーネントを GetComponent() を使って取得し、ポリモーフィズム(多態性)を活用して各派生クラスの機能(Speak メソッド)を利用する方法を解説します。

2. クラスの構成

2.1 Animal クラス(抽象クラス)

Animal クラスは MonoBehaviour を継承した抽象クラスとして定義し、抽象メソッド Speak() を宣言します。これにより、直接インスタンス化されることを防ぎ、派生クラスでの実装を強制します。

using UnityEngine;

public abstract class Animal : MonoBehaviour
{
    // 抽象メソッド:派生クラスで必ず実装する必要がある
    public abstract void Speak();
}

2.2 Dog クラス

Dog クラスは Animal クラスを継承し、Speak() メソッドをオーバーライドして犬の鳴き声「ワンワン」を出力します。

using UnityEngine;

public class Dog : Animal
{
    public override void Speak()
    {
        Debug.Log("ワンワン");
    }
}

2.3 Cat クラス

Cat クラスも Animal クラスを継承し、Speak() メソッドをオーバーライドして猫の鳴き声「ニャーニャー」を出力します。

using UnityEngine;

public class Cat : Animal
{
    public override void Speak()
    {
        Debug.Log("ニャーニャー");
    }
}

2.4 Test クラス

Test クラスは、同じ GameObject にアタッチされた Animal コンポーネント(Dog または Cat)を GetComponent() を使って取得し、Speak() メソッドを呼び出すサンプルです。

※ 注意: Animal クラスが抽象クラスでない場合は、 [RequireComponent(typeof(Animal))] 属性を使用できますが、、Animal クラスを抽象クラスに変更すると、抽象クラスは直接インスタンス化できず自動追加も行われません。
そのため、Test クラスには [RequireComponent] 属性は付与せず、必ず Dog または Cat などの具体的な Animal の派生クラスが同じ GameObject にアタッチされるように設計してください。

ただし、Testクラスをアタッチする前に、Dogクラスをアタッチすると派生クラスのためエラーになりませんがわかりにくいので推奨されません

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        // 同じ GameObject にアタッチされている Animal(=Dog または Cat)コンポーネントを取得
        Animal animal = GetComponent<Animal>();

        if (animal != null)
        {
            // 取得したコンポーネントに対して、実際のクラス(Dog/Cat)の Speak() が実行される
            animal.Speak();
        }
        else
        {
            Debug.Log("Animal コンポーネントが見つかりませんでした。");
        }
    }
}

3. 使用方法

  1. スクリプトの準備
    上記の各コードをそれぞれ Animal.csDog.csCat.csTest.cs として、プロジェクト内の Scripts フォルダなどに保存します。
  2. GameObject の作成とコンポーネントの追加
    • Unity のシーン上に空の GameObject を作成します。
    • 作成した GameObject に Test スクリプトをアタッチします。
    • 同じ GameObject に必ず Dog または Cat のいずれか、もしくは両方の具体的な Animal 派生クラスのコンポーネントをアタッチしてください。
  3. シーンの再生
    シーンを再生すると、Test クラス内の Start() が実行され、GetComponent() により Dog または Cat のコンポーネントが取得され、各クラスに応じた鳴き声がコンソールに出力されます。

4. [RequireComponent] 属性使用時の注意点(抽象クラスの場合)

4.1 現象

  • エラー発生:
    以前は [RequireComponent(typeof(Animal))] 属性を用いていましたが、Animal クラスを抽象クラスに変更すると、Unity は抽象クラスをコンポーネントとして追加できないため、Test コンポーネントを先にアタッチした際にエラーが発生します。

4.2 理由

  • 抽象クラスの特性:
    抽象クラスは直接インスタンス化できません。
  • RequireComponent の動作:
    [RequireComponent] 属性は、指定された型のコンポーネントが必ず存在するように自動追加を試みますが、抽象クラスはインスタンス化できないため、自動追加が行えず、エラーとなります。

4.3 対処方法

  • RequireComponent 属性の削除:
    Animal クラスが抽象クラスである場合、Test クラスから [RequireComponent(typeof(Animal))] 属性を削除してください。
  • 必ず具体的な派生クラスをアタッチ:
    プロジェクト設計上、GameObject に Dog または Cat といった具体的な Animal の派生クラスが必ずアタッチされるように管理するか、実行時に GetComponent() の結果が Dog や Cat であるかチェックするようにしてください。

この資料を参考に、抽象クラスを利用した Unity のポリモーフィズムと、[RequireComponent] 属性使用時の注意点を理解し、実際のプロジェクトに適切に応用してください。

Unity,継承

Posted by hidepon