はじめに
Unityで少し規模のあるゲームを作り始めると、次のような悩みにぶつかることがあります。
・定数や設定値がスクリプトに散らばっている
・同じデータを複数のオブジェクトが持っている
・数値調整のたびにコードを書き換えている
こうした問題を解決するために用意されているのが ScriptableObjectです。
ScriptableObjectとは?
ScriptableObject とは、シーンやGameObjectに依存しない、データ専用のオブジェクトです。
MonoBehaviourと同じくC#のクラスですが、GameObjectにはアタッチしません。
代わりに、プロジェクト内の「アセット」として存在し、複数のスクリプトから共有されるという特徴を持っています。
処理は MonoBehaviour、データは ScriptableObjectという役割分担が基本です。
基本的な書き方
まず、ScriptableObjectを継承したクラスを作ります。
using UnityEngine;
[CreateAssetMenu(menuName = "GameData/EnemyData")]
public class EnemyData : ScriptableObject
{
public int maxHp;
public int attack;
public float speed;
}
UnityエディタでAssetMenuを作成することで、これを基にしたデータを作ることができます。
次に、このデータを利用するクラスの書き方です。
using UnityEngine;
public class Enemy : MonoBehaviour
{
public EnemyData data;
void Start()
{
Debug.Log($"HP: {data.maxHp}, 攻撃力: {data.attack}");
}
}
ここで重要なのは、Enemy自身は数値を持っておらず、ScriptableObjectを「参照」しているだけという点です。
例えば、同じEnemyDataを複数のEnemyが参照しているとします。
このとき、Enemyが10体いてもEnemyDataは1つだけです。
つまり、同じ設定データを、全員が参照しているという状態になります。
なぜ便利?
これのなにが便利かというと、同じ構造を持ったデータを大量生産できる点です。
データに特化したScriptableObjectを使うことで、敵のステータスや、魔法の効果といったものが扱いやすくなります。
おわり
まとめると以下の通りです。
・ScriptableObjectは「データ専用」のクラス
・GameObjectやシーンに依存しない
・複数のオブジェクトで同じデータを共有できる
・処理とデータを分離すると、設計がきれいになる
「この変数、本当にMonoBehaviourに持たせるべきか?」
そう考え始めたら、ScriptableObjectを検討するタイミングです。