View on GitHub

adventure-cube

ScriptableObject

Unity状のデータを管理するときに便利な話です。

ScriptableObjectでデータを管理する

ScriptableObjectは、Unity上で以下の特性を持つデータ構造体です。
・Inspectorと違い、実行終了してもデータが残る
・ゲーム内でクラスとして使用できる(関数や別の変数定義もできる)
・アセットとして読み込みができる

シリアライズ可能

ScriptableObjectに適用するデータは、シリアライズ可能である必要があります。
シリアライズ可能で確認しましょう。

エディタ拡張とのコラボ

ScriptableObjectそのままでは設定/使用しづらいデータとかはあります。
そういう時にエディタ拡張を使って、入力や設定をヘルプするという手法を使います。

エディタ拡張はやりすぎるとゲーム進行が一切進まなくなり、沼から帰ってこれなくなります。
気を付けましょう。

実例を用意したので、確認してみてください。

ScriptableObjectの例

[CreateAssetMenu(fileName = "CubeSheet", menuName = "ScriptableObjects/CubeSheet", order = 1)]
public class CubeSheet : ScriptableObject
{
    [Serializable]
    class CubeAsset
    {
        public int Id;
        public string Key;
        public MonoBlock Block;
    }

    [SerializeField] List<CubeAsset> CubeAssetList = new List<CubeAsset>();

    public MonoBlock GetAsset(int id)
    {
        if (id < 0) return null;
        if (id >= CubeAssetList.Count) return null;

        return CubeAssetList[id].Block;
    }

    public string GetAssetKey(int id)
    {
        if (id < 0) return null;
        if (id >= CubeAssetList.Count) return null;

        return CubeAssetList[id].Key;
    }

    public int GetRandomCubeId(MonoBlock.BlockType type)
    {
        //いろいろ重いけどとりあえず我慢
        var list = CubeAssetList.Where(c => c.Block && c.Block.Type == type);
        int count = list.Count();
        if (count == 0) return 0;

        int d = UnityEngine.Random.Range(0, count);
        return CubeAssetList.IndexOf(list.ElementAt(d));
    }

    public int GetRandomCubeIdWithRare(MonoBlock.BlockType type, int rare)
    {
        //いろいろ重いけどとりあえず我慢
        var list = CubeAssetList.Where(c => c.Block && c.Block.Type == type && c.Block.Rare == rare);
        int count = list.Count();
        if(count == 0) return 0;

        int d = UnityEngine.Random.Range(0, count);
        return CubeAssetList.IndexOf(list.ElementAt(d));
    }
}

お約束系

まず、この一文をクラスの前につけます。

[CreateAssetMenu(fileName = "CubeSheet", menuName = "ScriptableObjects/CubeSheet", order = 1)]

これは、Unityに、このScriptableObjectを作るためのメニューを定義するよ、という命令です。
Unity用の命令です。

記入すると、Projectウインドウで右クリックした際、ScriptableObjectsというメニューと、その中の項目にCubeSheetというのが出てきます。
それを押すと、このクラス型のデータを作ることができるようになります。

[Serializable]

クラス内で使用するデータは、すべてシリアライズ可能(Unityのエディタ上でで設定できる状態)にしてください。

[Serializable]
Class CubeAsset
{
    public int Id;
    public string Key;
    public MonoBlock Block;
}

[SerializeField] List<CubeAsset> CubeAssetList = new List<CubeAsset>();

関数定義

ふつうにクラスとして使用できるので、データを整形して返すことができます。
便利なので必要に応じて追加ましょう。