はかせのラボ

私の頭の中を書いていく雑記ブログです

Unity ScriptableObject②

あいさつ

どうも、はかせです。
今回は前回に続きScriptableObjectについて、
実際にどんな感じに使うのか編です。

使用例① データ

多分ScriptableObjectの存在を知っている人ならば
真っ先に思いつくであろう使い方です。

ScriptableObjecはシーンロード等で勝手にデータが初期化されません。
その特性を利用して簡易的なデータベースやセーブデータとして利用するわけです。

[CreateAssetMenu(fileName = "Data", menuName = "Data")]
public class TestData : ScriptableObject
{
    public List<string> TestDataString;
}

ちゃんとした使い方をしたければ
ゲッターやらセッターやらをしっかり作って運用するべきかもですが、
簡易的なデータベースとかで使うなら素直にpublicでデータ持っていいと思います。
(どうせ色んなとこから参照やら書込やら起こるんでしょうし)

ちなみに設定データとかインスペクター上からのみ弄るデータの場合は
こんな感じで使うことが私は多いです。

[CreateAssetMenu(fileName = "Data", menuName = "Data")]
public class TestData : ScriptableObject
{
     [SerializeField]
    private List<string> mTestDataString;
    public IEnumerable<string> GetTestData() { return mTestDataString; }
}

戻り値でListではなくIEnumerableにしているのは
データの中身をあまり変えてほしくないからですね。
もちろんArrayやListにキャストすれば変えれるんですが、
あくまで「あまり」なのでどうしても変えたい場合は変えれるようにって感じです。

使用例② モデルとか単機能提供

これはステートマシンの状態ごとの処理だとか、
以前書いたMVPパターンのモデルとかそういった
単機能提供を行うクラスをインスタンス単位で操作したいときに使えます。

この形にすることで使用インスタンスを切り替えるだけで
機能の切り替えが実現できます。

使用例①と②を合わせたなにか

まぁくどくどこんな使い方あるよーっていってもわかりづらいと思うんで
実際に使ってみます。

今回はこんな感じで作ってみます。
f:id:hakase0274:20190414231258p:plain
DataとModelがScriptableObjectですね。

まずはDataから。
これは素直に文字列をもつだけとします。
コードは既に使用例①で挙げたものを使うので割愛します。

次にModelですが、
こちらはDataから文字列を読み出しPresenterに渡すというものにします。
ただ
・何も加工せず生のまま渡す
・前後にタグをつけて色を変えて渡す

こんな感じで種類を作って切り替えれるようにしてみます。

ではコードです。
まずはノーマル版

[CreateAssetMenu(fileName = "Model",menuName = "Model")]
public class TestModel : ScriptableObject
{
    public TestData Data;
    public virtual string GetData(int dataNum)
    {
        return Data.TestDataString[dataNum];
    }
}

次に色変え版
(めんどいから継承でやりました)

[CreateAssetMenu(fileName = "Model2", menuName = "Model2")]
public class TestModel2 : TestModel
{
    public override string GetData(int dataNum)
    {
        return "<color=red>" + Data.TestDataString[dataNum] + "</color>";
    }
}

そして最後にViewとPresenterです。
View

public class TestView : MonoBehaviour
{
    private Text mText;
    // Start is called before the first frame update
    void Start()
    {
        mText = GetComponent<Text>();
    }

    public void UpdateText(string text)
    {
        mText.text = text;
    }
}

Presenter

public class TestPresenter : MonoBehaviour
{
    public TestModel Model;
    public TestModel2 Model2;
    public TestView View;

    private TestModel mUseModel;

    private void Start()
    {
        mUseModel = Model;
    }
    // Update is called once per frame
    void Update()
    {
        //Spaceキーでノーマル版に
        if (Input.GetKeyDown(KeyCode.Space))
        {
            mUseModel = Model;
            View.UpdateText("Change To Model");
        }
        //エンターキーで色変え版に
        if (Input.GetKeyDown(KeyCode.Return))
        {
            mUseModel = Model2;
            View.UpdateText("Change To Model2");
        }
        //ブログだと長いからカット
        #region 数字をキーボードから入力してそれに対するデータをModelから取り出しViewに渡す
        #endregion
    }
}

そして実行結果のGIFです。
ちょっと長いです。
f:id:hakase0274:20190414232217g:plain
(今日の晩御飯のチーズダッカルビに気管がやられた旨が流れてますw)

あとがき

今回はScriptableObjectを実際に使ってみるでした。
実際にそう頻繁に使うかと聞かれると怪しいですが
ちょっと変わったことしたいと思ったら結構便利です。

そしてまじチーズダッカルビ許すまじ

それでは今回はこの辺でノシ