ScriptablObjectを使って、アイテムや武器などのバリエーションを増やそう!

ころもちゃん

敵や装備みたいな、バリエーションがたくさんあるものは、どうやって作ればいいの??

本記事の内容

・データベースとはなにか?
・データベースScriptableObjectを使おう

目次

同系統のバリエーションを増やすにはScriptablObjectを使おう!

ScriptablObjectを使って、設定値をまとめて管理しよう!

ゲームを作っていると、敵・アイテム・装備・スキルなど、同じような機能を持ったパラメータ違いのオブジェクトが複数必要になることがあります。
ポケモンを例にすると、「モンスターボール」、「スーパーボール」など捕獲率のパラメータ違いのアイテムが出てきますよね。このように同じ系統のオブジェクトを複数管理するのに適したUnityの機能が「ScriptableObject」です。

たとえば、「モンスターボール」・「スーパーボール」・「きずぐすり」・「まんたんのくすり」、というアイテムをゲームに実装するとします。

これらのアイテムには以下のパラメータを持たせるとします。

  • アイテムID(こういったリストを作るときには、IDがあるとなにかと便利)
  • アイテムのアイコン
  • アイテムの種類
  • アイテムの名前
  • アイテムの説明
  • 効果値(例えばモンスターボールなら50%、スーパーボールなら70%、きずぐすりなら20、まんたんのくすりなら999)

すると、以下のような表が出来上がります。

IDアイコン画像種類名前説明効果値
100ボールモンスターボール低確率で捕まえる50
101ボールスーパーボール中確率で捕まえる70
200回復きずぐすりHPを20回復する20
201回復まんたんのくすりHPを満タンまで回復する999
アイテムデータベース

これらをUnity内で管理できるのが、ScriptableObjectです。

ScriptablObjectのサンプル

実際にこれらのアイテムをUnity内で使う方法を解説してきます。

STEP
ScriptablObjectのスクリプト作成

スクリプトファイルを作って、以下サンプルのコードを貼り付けます。

using UnityEngine;

// アイテムの種類を表す列挙型
public enum ItemType
{
    Ball,   // ボール
    Heal    // 回復
}

[System.Serializable]
public class Item
{
    public int id;             // アイテムのID
    public Sprite icon;        // アイテムのアイコン画像
    public ItemType itemType;  // アイテムの種類
    public string itemName;    // アイテムの名前
    [TextArea]
    public string description; // アイテムの説明
    public int effectValue;    // 効果値
}

[CreateAssetMenu(fileName = "ItemList", menuName = "Inventory/ItemList")]
public class ItemList : ScriptableObject
{
    public Item[] items;

    /// <summary>
    /// 指定されたIDのアイテムを返す
    /// </summary>
    /// <param name="id">検索するアイテムのID</param>
    /// <returns>該当するアイテム。見つからなければnull。</returns>
    public Item GetItemById(int id)
    {
        foreach (var item in items)
        {
            if (item.id == id)
            {
                return item;
            }
        }
        Debug.LogWarning($"Item with ID {id} not found.");
        return null;
    }
}

ScriptableObjectは通常のC#のスクリプトとは書き方が違います。
特徴としては、冒頭に[CreateAssetMenu(...)]とあるところです。

これはScriptablObjectを作るためのメニューを設定するというコードです。このコードによって、プロジェクトビューで右クリックすると、ScriptablObjectを生成することが出来ます。

また、ScriptablObjectには、メソッドを入れ込むことが出来ます。
GetItemByIDメソッドでは、IDを渡すとそれに該当するItemのデータを返してくれるメソッドです。

STEP
ScriptablObjectの値をインスペクタから登録

Step1のスクリーンショットにあるメニューからScriptablObjectが作成されると、以下のような青い箱が表示されます。

これが、ScriptablObjectです。ここに設定値を登録します。
先程の例にあるような設定値を登録します。

STEP
ScriptablObjectのデータを読み込むスクリプトの作成

これらのScriptablObjectが設定出来たら、最後にScriptablObjectで設定した値を取得する方法です。
今回はサンプルとして、ScriptablObjectから値を取得し、UIに表示するスクリプトを作ってみます。
新規でスクリプトを作成し、以下のコードを作りました。

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class SampleItemDataSetter : MonoBehaviour
{
    [SerializeField] private ItemList itemList; // ScriptableObjectをアタッチ
    [SerializeField] private Image itemIconImage; // アイコン表示用
    [SerializeField] private int itemId;       // 表示したいアイテムのID
    [SerializeField] private TMP_Text itemNameText;    // アイテム名表示用
    [SerializeField] private TMP_Text itemDescriptionText; // 説明表示用
    [SerializeField] private TMP_Text itemEffectValueText; // 効果値表示用

    private void Start()
    {
        DisplayItemDetails(itemId);
    }

    private void DisplayItemDetails(int id)
    {
        // IDに該当するアイテムを取得
        var item = itemList.GetItemById(id);

        if (item != null)
        {
            itemIconImage.sprite = item.icon;
            itemNameText.text = item.itemName;
            itemDescriptionText.text = item.description;
            itemEffectValueText.text = $"Effect: {item.effectValue}";
        }
    }
}

ヒエラルキーウィンドウに対応するTextMeshPro、Imageオブジェクトを配置します。

親オブジェクトのItemに、先程作成したSampleItemDataSetterをアタッチし、インスペクタから対応する項目をアタッチします。

これで再生してみましょう。以下のようにUIにScriptablObjectで設定した値が表示されていれば成功です。

ScriptableObjectの上手な向き合い方

最後に、個人的にScriptablObjectを作る時の気をつけていることをまとめておきます。

ScriptablObjectの値は更新しないものだけを設定する

ScriptablObjectは基本的に静的なデータを扱うためのものですが、ゲーム中に値が変動するものを扱うのには適していません。レベルごとのパラメータ値など、ゲームプレイ次第で値が変わることが無いようなデータを設定するようにしましょう。

逆に、シーンを跨いでも同じ値でセットしておきたいなどの場合には、ScriptablObjectを使うと整合性の取れたデータを扱うことができるのでオススメです。

ScriptableObjectから欲しいデータを取得するメソッドを入れておく

自作のScriptablObjectは、配列(リスト)形式になることが多いです。
配列(リスト)からデータ取得する場合、取得するためのメソッドをScriptablObject側に仕込んでおくと、設計がキレイになりやすいです。

今回のサンプルだと、以下の部分です。

    private void DisplayItemDetails(int id)
    {
        // IDに該当するアイテムを取得
        var item = itemList.GetItemById(id);

        if (item != null)
        {
            itemIconImage.sprite = item.icon;
            itemNameText.text = item.itemName;
            itemDescriptionText.text = item.description;
            itemEffectValueText.text = $"Effect: {item.effectValue}";
        }
    }

ほかにも、条件に応じてフィルタリングして対応するリストを返すメソッドなど、必要に応じて必要なデータを取得するロジックを仕込んでおくとよいでしょう。

まとめ

ScriptableObjectを使うと、設定値を一律管理できるようになるので、バリエーションを増やすことが容易になります。内容が充実したゲームを作るには必須の機能でしょう。
ぜひ使い方をマスターしてみてください。

それでは素敵なゲーム制作ライフを!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ゲーム制作の敷居を下げ、もっと多くの人にゲーム作りを楽しんでもらうために、ゲームをカンタンに作る方法を”網羅的に”解説しています。
よかったらブックマークお願いします。
Twitter(X)もよければフォローお願いします。

コメント

コメント一覧 (1件)

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次