【Unity】クラス設計におけるインターフェイスの役割【C#】

この記事は約5分で読めます。

まず初めに断っておきますと、今回の記事は自分の備忘用です。

クラス設計を勉強していく中で見つけたこちらの記事がとても分かりやすかったので、実際にインターフェイスを真似して作ってみました。そんな記事です。

参考にさせていただいたスライド

こちらは、とりすーぷさんと言う方がまとめたスライドのようです。(すいません勝手にリンク貼らせていただきます)

この方は、この他にもクラス設計について分かりやすく、たくさんの記事をまとめている方で、初心者の私でも理解できる内容でした。

インターフェイスの使い方

まず先に悪い例を

初心者がやりがちな当たり判定の実装方法

触れたオブジェクトのTagによって処理を分けると言うものです。

(ちなみに私もこんな感じで実装してました)

触れたTagで判定!

コードにするとこんな感じですね。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision)
    {
        GameObject hit = collision.gameObject;

        switch (hit.tag)
        {
            case "Enemy":
                Debug.Log("Enemy は ダメージを食らった");
                break;


            case "Bomb":
                Debug.Log("爆発!");
                break;
        }
    }
}

Tag判定のどこが問題なのか?

このTag判定Switch文が意外にも問題だそうです。

私も薄々感づいてました。自作アプリに機能がどんどん増えるたびに苦痛も増えていましたから!

「敵の種類が増えたらコード書き直すの?」と言う問題ですね。あるあるですね。

クラス設計における良い例

この問題を解消してくれるのがインターフェイス(Interface)なのです。

「インターフェイス」って何?って人は、とりすーぷさんの記事を見てください。

このインターフェイスを使うと依存関係を反対にできるため、敵キャラが増えてもコードを書き直す必要がなくなります。

依存関係の少ない状態という事です。

インターフェイスを作成

インターフェイスは慣習として頭に ” I ” を付けるようです。

頭にIが付いていたら「あ、インターフェイスだな」という事ですね。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IReceiveDamage
{
    void ReceiveDamage(float damage);
}

コードはこれだけです。

このインターフェイスを継承したクラスは、このReceiveDamageメソッドを必ず実装しなくてはいけません。ただインターフェイスの機能はただそれだけです。

そういうルールを作る事が肝なんですね。

Enemyクラスにインターフェイスを継承させる

コードの書き方は MonoBehaviour の後に先ほど作ったインターフェイス名「 , IReceiveDamage」を足すだけです。

そしてReceiveDamageメソッドを作りましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour, IReceiveDamage
{
    public void ReceiveDamage(float damage)
    {
        Debug.Log("Enemy は " + damage + "ダメージ食らった");
    }
}

同様の手順で Bomb クラスにもインターフェイスを継承させます。

ReceiveDamageメソッド は実装しますが、処理は少し変えてみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bomb : MonoBehaviour, IReceiveDamage
{
    public void ReceiveDamage(float damage)
    {
        Debug.Log("爆発!");
    }
}

Playerクラスの攻撃!

Playerクラスが敵にダメージを与える際に、インターフェイスを経由する方法がこちら

これで依存関係が解消され、敵がいくら増えようが Playerクラスのコードを直す必要は発生しません。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision)
    {
        // インターフェイスを取得
        var hit = collision.gameObject.GetComponent<IReceiveDamage>();

        // 触れた相手がダメージを受ける
        hit.ReceiveDamage(10f);
    }
}

これで触れた敵にダメージを与える事が可能です。

とりあえず今回の記事はここまで!

コメント

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