とあるプログラマの備忘録

都内某所に住むプログラマが自分用に備忘録を残すという趣旨のブログです。はてなダイアリーから移動しました!

Unity ScriptableObjectはバトルデータに向いていると思う

久しぶりのブログです。
アプリ作成は進んでいるのですが、いかんせんブログのネタになる作業をしていない&見せられないよ!
という事であまりブログが書けてません。。むしろブログ書きたいのに。。。

今日の話はScriptableObjectが結構使えそうだったのでその話です。

ScriptableObjectについてはこちらの記事が丁寧に書かれていますのでこちらを参考にしてください。

tsubakit1.hateblo.jp

それでは問題です。

ステージ毎に敵の出現ポイントやタイミングを変更したいのですが、どうしたらいいでしょうか?

よくある事です、 ○秒後に○の敵が出現その後○秒後にボスが出現といった
いわゆるバトルデータ(シナリオデータ)をどうやって実現しましょうか?というお話です。

幾つかすぐに出てくる答えとしては、

csvjsonでデータを作成してなんやかんやパースすればええやん
・シナリオDBでも作って適当に出せるようにしたらええやん
・最低データのみ保持してランダムで出現させればええやん

全部正解だと思います。 作ろうとしているものの用途に合わせて上記で選ぶのも良いでしょう。 ですが、Unityの場合はScriptableObjectがこれに適合している気がします。

なぜなら、Inspector上で値を変更しながらバトルデータを作成できるから!

です

という事で早速作成します。

まずは構造を決めます。

[Scripts/QuestBattleData]として保存します

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[System.Serializable]
public class QuestBattleData : ScriptableObject {

    //適当なパラメータ
    public int param1;
    public Rect param2;

    //敵が出現する場所とID
    public List<EnemyDetail> entryEnemy;
    
}

[System.Serializable]
public class EnemyDetail{
    public int enemy_id;
    public Vector3 enemy_pos;
}

構造を型にアセットを作成できるようにします。
[Editor/CreateBattleData]として保存します

using UnityEngine;
using UnityEditor;
using System.Collections;

public class CreateBattleData : MonoBehaviour {
    [MenuItem("Assets/Create/CreateBattleData")]
    public static void CreateAsset()
    {   
        QuestBattleData item = ScriptableObject.CreateInstance<QuestBattleData>();

        //アセットを保存するパス
        string path = AssetDatabase.GenerateUniqueAssetPath("Assets/Resources/QuestBattleData/" + typeof(QuestBattleData) + ".asset");
        
        AssetDatabase.CreateAsset(item, path);
        AssetDatabase.SaveAssets();
        
        EditorUtility.FocusProjectWindow();
        Selection.activeObject = item;
    }
}

これでAssets/Resources/QuestBattleData/フォルダを作成して、
Project > Createメニューを開くと一番下に出てきます。

f:id:raharu0425:20150821184403p:plain

これで作成されたアセットはこんなInspectorになってます。

f:id:raharu0425:20150821184517p:plain

あとはQuestBattleDataとしてスクリプトにアタッチすればOK

public QuestBattleData battleData;

f:id:raharu0425:20150821185329p:plain

スクリプトからQuestBattleDataを参照する事が可能です。
また、Resouces/に入れておけば動的にアタッチする事も出きますし、
.assetなのでこのままAssetBundle化してLoadしてもよいでしょう。

そして何より、

Inspector上で動的にゲームバランスを整えながらバトルデータを作成できます!

これにより、CSVJsonのようにパーサーを用意しなくても良いですし、
DBデータでマスタデータを更新して検証DBに反映してとかやらなくても良いし、
値を追加変更する場合も影響範囲がわかりやすいという状態です(スバラっ!)

という事で今回はScriptableObjectのお話でした、
他に良い方法があるよ!とかこんな使い方があるよ!?とか
ご意見マサカリ歓迎しております。