🌊

[unity] インスペクターで interface を使用する

2025/02/28に公開

[SerializeField] SerializableInterface<IEnemy> enemy;

unity 標準の機能では、interface をインスペクターに表示できない。
でも、使いたい。そんな場合に便利なアセット、SerializableInterface を紹介します。

掲載サイト

https://openupm.com/packages/net.tnrd.serializableinterface/

OpenUPM を使ってインストールします。
OpenUPM ってなんのこっちゃ? という人が多いかもしれませんが、PackageManager 経由で取得できる方法があります。

OpenUPM

まず、掲載サイトの URL (https://openupm.com/packages/net.tnrd.serializableinterface/) のうち、net.tnrd.serializableinterface が必要です。
(これをスコープといいます。コピーしておきましょう)

unity の Edit > Project Settings > Package Manager を開きます。

Name: OpenUPM
URL: https://package.openupm.com
Scope(s): net.tnrd.serializableinterface

次のように記述し、save します。

Package Manager

次に Window > Package Manager を開きます。

左下のジグゾーパズルのようなマークをクリック。

Serializable Interface をインストールします。

使い方

サンプルの前準備として、EnemyA, EnemyB と、それを共通化するインターフェイス IEnemy を作成します。

IEnemy.cs
public interface IEnemy
{
    public void DebugLog();
}
EnemyA.cs
using UnityEngine;

public class EnemyA : MonoBehaviour, IEnemy
{
    public void DebugLog()
    {
        Debug.Log("EnemyA");
    }
}
EnemyB.cs
using UnityEngine;

public class EnemyB : MonoBehaviour, IEnemy
{
    public void DebugLog()
    {
        Debug.Log("EnemyB");
    }
}

次に、この EnemyA・EnemyB をインスペクターから登録できるクラス Main.cs を作成します。

Main.cs
using TNRD;
using UnityEngine;

public class Main : MonoBehaviour
{
    [SerializeField] SerializableInterface<IEnemy> enemy;

    void Start()
    {
        enemy.Value?.DebugLog();
    }
}

SerializableInterface<IEnemy> が最初のポイントです。

この Main を GameObject にアタッチしてください。

None(Object) というメンバーが表示されていれば成功です。
ここには IEnemy を継承したクラス(EnemyA、EnemyB)を入れて実行すると、それぞれの DebugLog() が実行されることを確認できます。

enemy.Value?.DebugLog(); と、Value を挟むのが次のポイントです。
? は null チェック不要であればつけなくても OK です。

そもそも interface って必要?

いろいろ流派もあるかと思いますが、個人的に interface は「適切に使えば、将来起こり得る問題を防ぎやすい」記法だと思います。
具体的に考察した記事もありますので、よければ一緒にご覧ください。

https://zenn.dev/catsnipe/articles/aa3ea5f17a8c8d

Discussion