読者です 読者をやめる 読者になる 読者になる

いんでぃーづ

個人でゲーム開発してる上で吸収したモノたち紹介。UnityからGIMPまでなんでも。デザインとかゲーム論まで語っちゃうよ的なアレ。

MENU

Unity : 不変データはScriptableObject を使って管理するとドヤ顔できるかもしれない

{スポンサーリンク}
{スポンサーリンク}

目次


敵の攻撃力や防御力など、「ゲーム全体で共通かつ不変」なデータを持たせたい場合は数多くあります。

そんな時つい、やってしまいがちなのが、プレハブ自体に値を持たせる方法。

f:id:sugar_affordance:20160625233559p:plain:w400

こんなふうに持たせてしまうと、Instantiateするたびにこれらの変数がメモリに確保されてしまいます。

でもスクリプトにconst変数で持たせるのもツライなあ、インスペクターで設定したいなあ…そんなふうに悩んでいたことも、あったようななかったような。

解はひとつ!

ScriptableObject ならインスペクターで設定できつつメモリは一箇所で済みます

http://docs.unity3d.com/ja/current/Manual/class-ScriptableObject.html


ScriptableObjectを作成する

まず、とにもかくにもScriptableObjectを作ってみましょう。

以下のようなスクリプトを作成します。 Power, Speed, Lifeがインスペクターで設定できる変数です。

[CreateAssetMenu]
public class EnemyDataTable : ScriptableObject {

    public int Power, Speed, Life;

}

MonoBehaviour でなく、ScriptableObjectを継承すること!
また、CreateAssetMenuというAttributeがついてますが、これをつけることにより、メニューからScriptableObjectアセットが作成可能になります。

f:id:sugar_affordance:20160625233602p:plain:w400

Assets > Create から、作成したクラス名が選択できるようになってますね。

ポチっとな。

f:id:sugar_affordance:20160625233606p:plain:w500

プロジェクトビューで見ると、Assetが作成されてます。

ScriptableObject のデータを設定する

まずScriptableObjectのデータをインスペクターで設定します。

f:id:sugar_affordance:20160625233609p:plain:w400

次に、値を参照したいスクリプトで、作成したScriptableObjectクラスをメンバとして持ちます。

public class Enemy : MonoBehaviour {

    [SerializeField]
    EnemyDataTable data;         // 作成したScriptableObjectクラス

}

最後に、作成したScriptableObjectをインスペクタでメンバ変数として設定します。

f:id:sugar_affordance:20160625233611p:plain:w400

値を参照するときは以下のように、プロパティとして参照します。

void Start() {
     Debug.Log(""+data.Life);
}

これでメモリを節約しつつ、共有データを持てるんです!

データを書き換えられないようにスクリプトを修正する

現状だとデータを public で持っているので、他のスクリプトから書き換えられてしまいますね。
それを防ぐには、スクリプトで以下のように public な getter を作成し、シリアライズ可能な変数にアクセスします。

[CreateAssetMenu]
public class EnemyDataTable : ScriptableObject {

    [SerializeField]
    int power, speed, life;

    public int Power {
        get {
            return power;
        }
    }
    public int Speed {
        get {
            return speed;
        }
    }

    public int Life {
        get {
            return life;
        }
    }
}

こうすることでインスペクタから設定しつつ、スクリプトから書き換えるのを防ぐことができます。


便利ですねえ。ScriptableObject。
これでもうちょっと作り方が簡単だったらね…という方は → ここ

Amazon.co.jpアソシエイト