よくやりそうなダメージ判定
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を取得して、ダメージ処理を呼び出しています。
これにより、敵が増えてもプレイヤー側は、このままのコードで最初の動画のように、敵にダメージを与えることが出来ます。