目次
敵の攻撃力や防御力など、「ゲーム全体で共通かつ不変」なデータを持たせたい場合は数多くあります。
そんな時つい、やってしまいがちなのが、プレハブ自体に値を持たせる方法。
こんなふうに持たせてしまうと、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アセットが作成可能になります。
Assets > Create から、作成したクラス名が選択できるようになってますね。
ポチっとな。
プロジェクトビューで見ると、Assetが作成されてます。
ScriptableObject のデータを設定する
まずScriptableObjectのデータをインスペクターで設定します。
次に、値を参照したいスクリプトで、作成したScriptableObjectクラスをメンバとして持ちます。
public class Enemy : MonoBehaviour { [SerializeField] EnemyDataTable data; // 作成したScriptableObjectクラス }
最後に、作成したScriptableObjectをインスペクタでメンバ変数として設定します。
値を参照するときは以下のように、プロパティとして参照します。
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。
これでもうちょっと作り方が簡単だったらね...という方は → ここ