⛳
【Unity】ScriptableObjectの使い方と落とし穴【コピペ可】
使い方と落とし穴シリーズ一覧
さっさと試したい人向け コピペ可コード
PlayerStatus.cs(ScriptableObject側 エディタ上で生成する側)
using UnityEngine;
[CreateAssetMenu(menuName = "Status/PlayerStatus")]
public class PlayerStatus : ScriptableObject
{
[SerializeField] private float hp = 100f;
public float HP => hp;
}
Player.cs(ScriptableObjectを利用する側)
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] private PlayerStatus status;
private void Start()
{
Debug.Log($"初期HP: {status.HP}");
}
}
使い方
1:Assetsフォルダ内で PlayerStatus.cs を作成
2:Player.cs をシーン上のオブジェクトにアタッチ
3:プロジェクトビュー → Create → Status → PlayerStatus でアセット作成
4:作成アセットを Player の status にドラッグ
一言
-
ScriptableObjectの習得で Unity への抵抗感がグッとなくなる (経験談) - 開発に必須…ではないが、Unity のディープな機能を色々扱っていく上で
最初の良いステップと考えています
ScriptableObjectを使用するケース
- 定数の管理
- キャラクタークラスごとの初期ステータス
- シーン間で共通する設定情報
ScriptableObjectの使い方
全体の流れ
ScriptableObject 継承
[CreateAssetMenu(menuName = "Status/PlayerStatus")]
public class PlayerStatus : ScriptableObject
{
[SerializeField] private float hp;
public float HP => hp;
//他なんかデータ色々
}
-
[CreateAssetMenu(menuName = "任意の名前")]を追加 -
MonoBehaviourをScriptableObjectに変更 - クラス内には後々エディタ上で操作したいデータを記述(例:
hp)
エディタ上で生成

- エディタ上で右クリック → Create → Status → PlayerStatus を選択するとプロジェクトビューに
PlayerStatusファイルが作成される -
[SerializeField],publicな変数はインスペクターから操作できる
他スクリプトで使用
public class Player : MonoBehaviour
{
[SerializeField] private PlayerStatus status;
private void Start()
{
Debug.Log($"初期HP:{status.HP}");
}
}
-
ScriptableObject(PlayerStatus)を参照して使うことができる
ScriptableObjectのメリット
- エディタ上で操作できるデータ群を作りやすい
- 複数シーンやゲーム全体にまたがったデータ群を作りやすい
-
静的で共用のデータに向いている(例:敵のHPや移動速度等の固定パラメータ)
- 全インスタンスが値を持つより、
ScriptableObject参照の方がメモリ使用量が抑えられる - Flyweightパターン実装に活用することもできる
- 全インスタンスが値を持つより、
オイラはこんな落とし穴に出会った
データ書き換えで想定外のやつも変わる
- 複数スクリプトで使用する場合に注意(そう珍しくない状況)
- スクリプトは
ScriptableObjectを参照する - そのため、「スクリプトA調整するか…」とうっかり参照元を変え、他にも影響が出てしまうケースがある
new() で生成
-
ScriptableObject継承クラスをnew()すると警告がでる(UNT0011) - この場合 Unity message methods(
OnEnable()とか)が正しく動作しない可能性がある - そのため、
CreateInstance()を代わりに用いる
var status = new PlayerStatus(); //UNT0011
var status = ScriptableObject.CreateInstance<PlayerStatus>(); //OK
- なお、これで作成した
ScriptableObjectはメモリ上にのみ存在するため、アセットとして保存したい場合は別途AssetDatabase.CreateAsset()が必要
実行中に書き換え → そのまま
- エディタで実行中、
ScriptableObjectのデータを書き換えても終了後そのまま - これはむしろ便利だが、
Monobehaviourとの挙動とは異なるので注意(終了後、元に戻る) - 筆者はその辺を勘違いしてパラメータで遊んでたら盛大にバグった経験アリ(99%筆者が悪い)
Discussion