スポンサーリンク

【Unity】敵の種類が増えても使えるダメージ判定

スポンサーリンク
c#
\楽天ポイント4倍セール!/
楽天市場
\商品券4%還元!/
Yahooショッピング

よくやりそうなダメージ判定

using UnityEngine;
//プレイヤークラス
public class Player : MonoBehaviour
{
    float _strength = 10;   //プレイヤー攻撃力

    //何か当たったら
    private void OnTriggerEnter2D(Collider2D collision)
    {
        GameObject hitObj = collision.gameObject; //ヒットしたゲームオブジェクトを取得
        
        //タグで敵を判断
        switch (hitObj.tag)
        {
            case "Slime":
                Slime slime = hitObj.GetComponent<Slime>(); //スライムクラスを取得
                slime.Damage(_strength);
                break;

            case "Goblin":
                Goblin goblin = hitObj.GetComponent<Goblin>(); //ゴブリンクラスを取得
                goblin.Damage(_strength);
                break;
        }
    }
}
using UnityEngine;
//スライムクラス
public class Slime : MonoBehaviour
{
    public void Damage(float damage)
    {
        Debug.Log("スライムダメージ");
    }
}
using UnityEngine;
//ゴブリンクラス
public class Goblin : MonoBehaviour
{
    public void Damage(float damage)
    {
        Debug.Log("ゴブリンダメージ");
    }
}

一見、プレイヤーが当たった時に、スライムとゴブリンのダメージ判定ができているので、問題ないように感じると思います。

ですが、この実装方法だと、敵の種類が増えていったときに、プレイヤーの当たり判定のSwitch文に敵を追加する必要が出てきてしまいます。

インターフェースを活用する

インターフェースとは、簡単に言うと「クラスで実装してほしい関数を必ず実装してね!」というルールを定義するものになります。

実際にダメージ用のインターフェースを実装してみましょう!

インターフェースの実装

//ダメージ用インターフェース
public interface IDamaged
{
    void Damage(float damage);
}

書き方は、クラスと似ていて、インターフェースの中に、実装させたいメソッドを定義します。
クラスと違う点は、定義した関数の中身は、記述しません。

中身の実装は、このインターフェースを使う側のクラスで、実装していきます。

では、先ほどのスライムとゴブリンにインターフェースを実装していきます。

using UnityEngine;
//スライムクラス
public class Slime : MonoBehaviour, IDamaged //インターフェースを実装
{
}

インターフェースは、クラスに継承するように使います。厳密には継承ではなく、インターフェースを実装するというほうが正しいです。

上記コードのように、インターフェースを実装しただけでは、コードを書いているエディタなどで、何かしらのエラーメッセージが出ると思います。

自分が使ってるエディタでは、"Slimeはインターフェースメンバー IDamaged.Damage(float)を実装しません"と出ています。

これは、「インターフェースを実装するなら、インターフェースの中にある関数を実装してね!」という、エラーメッセージです。

なので、スライムクラスに、ダメージ用の関数を実装します。

using UnityEngine;
//スライムクラス
public class Slime : MonoBehaviour, IDamaged //インターフェースを実装
{
    public void Damage(float damage)
    {
        Debug.Log("スライムダメージ");
    }
}

ダメージ用の関数を実装しました。これでエラーメッセージが出なくなったと思います。

ゴブリンクラスでも、同じように実装します。

using UnityEngine;
//ゴブリンクラス
public class Goblin : MonoBehaviour, IDamaged //インターフェースを実装
{
    public void Damage(float damage)
    {
        Debug.Log("ゴブリンダメージ");
    }
}

これで、スライムとゴブリン側の実装は完了です。

インターフェースの参照

最後に、プレイヤー側の当たり判定を修正していきます。

using UnityEngine;

public class Player : MonoBehaviour
{
    float _strength = 10;   //プレイヤー攻撃力

    //何か当たったら
    private void OnTriggerEnter2D(Collider2D collision)
    {
        GameObject hitObj = collision.gameObject;

        //毎回GetComponentするのは動作が重いので、敵かどうかをまず調べる(早期リターン)
        if (!hitObj.CompareTag("Enemy")) { return; }

        IDamaged damageHit = hitObj.GetComponent<IDamaged>(); //ヒットしたオブジェクトのIDamagedを取得する

        //ダメージ判定が実装されていなければ、ダメージ判例を行わない(早期リターン)
        if (damageHit == null) { return; }

        damageHit.Damage(_strength); //ダメージを与える
    }
}

ヒットしたオブジェクトのIDamagedを取得して、ダメージ処理を呼び出しています。
これにより、敵が増えてもプレイヤー側は、このままのコードで最初の動画のように、敵にダメージを与えることが出来ます。

タイトルとURLをコピーしました