一覧からScriptableObjectのカスタム作成と検索ができるScriptableObject拡張【Odin,Unity】

ゲームで敵を複数作るときに ScriptableObject を使っています.少ない数なら自分で画像や名前を追加して生成するというのはいいかもしれません. しかし,これを List<ScriptableObject>で管理する場合作成したものをリストに追加するというのは割と手間です そこで,リストから ScriptableObjectを自分の作りたいようにカスタマイズしながら作成でき,これらを検索できるようにエディタ拡張をOdinを使って作成していきます.

Demo

敵データの作成

各データからも再度ステータスを調節することができます

敵の個別データからステータスを再生成

作成したデータの検索

実装内容

  • リストから敵を作成(名前と画像の指定)
  • 敵の特徴を指定 →特徴に応じてステータスを生成時に決定できます
  • 重複した名前の敵が作られない,空の名前の敵などのミス作成の防止機能(ボタンにヴァリエーション機能)
  • リストの中に敵の検索機能(特徴を指定)
  • 各データからステータスの再生成

Odinについて

既存のワークフローに完璧に展開できる簡単な統合で、Odin を使ってすべてをシリアル変換することができ、80種類以上あるインスペクター属性やその他の機能を備えた、定型コードのない Unity を利用できます。

実装について

リストから敵を作成

実装方法

  1. CreateInstance<EnemyInfo>() を使って,ScriptableObject を作成します.
  2. enemyInfoの変数を設定します
  3. AssetDatabase.CreateAsset(enemy,createPath) を使って特定のフォルダに .assetを作成します

Code

private const string DATA_PATH = "Assets/TurnGame/Scripts/ScriptableObject/EnemyInfo/EnemyInfos/";

    [BoxGroup("敵生成"), LabelText("名前")] public new string name;
    [BoxGroup("敵生成"), LabelText("敵Sprite"),PreviewField(64)] public List<Sprite> sprites;
    [BoxGroup("敵生成"), LabelText("高HP")] public bool isHighHp;
    [BoxGroup("敵生成"), LabelText("高ATK")] public bool isHighAtk;
    [BoxGroup("敵生成"), LabelText("高攻撃速度")] public bool isHighAtkInterval;

    [Button("敵を追加",ButtonSizes.Large),BoxGroup("敵生成")][DisableIf("IsValidation")]
    public void CreateEnemy()
    {
        var enemy = CreateInstance<EnemyInfo>();
        enemy.name = name;
        enemy.enemySprites = sprites;
        if (isHighHp)
        {
            enemy.hp = Random.Range(3, 5);
            enemy.isHighHp = true;
        }
        else
        {
            enemy.hp = Random.Range(1, 3);
            enemy.isHighHp = false;
        }

        if (isHighAtk)
        {
            enemy.atk = Random.Range(3, 5);
            enemy.isHighAtk = true;
        }
        else
        {
            enemy.atk = Random.Range(1, 3);
            enemy.isHighAtk = false;
        }

        if (isHighAtkInterval)
        {
            enemy.atkInterval = Random.Range(3f, 6f);
            enemy.isHighAtkInterval = true;
        }
        else
        {
            enemy.atkInterval = Random.Range(6f, 10f);
            enemy.isHighAtkInterval = false;
        }
        var createPath = DATA_PATH + name + ".asset";
        AssetDatabase.CreateAsset(enemy,createPath);
        enemies.Add(enemy);
    }

ミス作成の防止機能

実装方法

  1. ListのExistsを使ってリスト内に同じものがあるかどうかを検索します.
  2. attributeの部分に [DisableIf("IsValidation")] を追加して,以下の関数を作成しました.

Code

private bool IsValidation()
    {   
        //名前が空鶴またはスペースの時,リストの中に同じ名前がある場合はボタンを非アクティブにする
        return name.IsNullOrWhitespace() || enemies.Exists(lName => lName.name == name);
    }

各データからステータスの再生成

実装方法

リストから作成する方法と同じ方法で,ステータスを再生成します.

参考サイト

baba-s.hatenablog.com

kan-kikuchi.hatenablog.com

https://her-hibari-blog.ssl-lolipop.jp/unity/odin-2/her-hibari-blog.ssl-lolipop.jp

https://bocchi-games.hatenablog.com/entry/odin-inspector-and-serializerbocchi-games.hatenablog.com