Unityで開発を続けていると、必ず一度は出てくるのが ScriptableObject です。

ですが実際は、

  • とりあえず使っている
  • なんとなくデータ保存用と思っている
  • 本当に必要なのか分からない

という状態になりがちです。

この記事では、ScriptableObjectの本質と正しい使い方を整理します。

この記事でわかること

  • ScriptableObjectは「データ専用のアセット」
  • シーンをまたいで共有できる
  • staticより安全
  • 設計レベルでゲーム構造を綺麗にできる
  • ただし「セーブデータ用途には向かない」

ScriptableObjectとは?

ScriptableObjectとは「Unity内でデータをアセットとして保存できる仕組み」です。

ScriptableObjectの作り方

以下のようにスクリプトをまずは作成します。

using UnityEngine;

[CreateAssetMenu(fileName = "ClassName", menuName = "Game/ClassName")]
public class ClassName : ScriptableObject
{
    public string characterName;
    public int hp;
}

作成ができたら、以下のようにして呼び出します。
EditorのProjectウィンドウで右クリック → Create → Game → CharacterData

MonoBehaviourとScriptableObjectの違い

項目MonoBehaviourScriptableObject
存在場所シーンの中に存在するProjectフォルダに保存される
シーン変更時シーンを消すと一緒に消えるシーンを変えても消えない
データ共有基本的に個別管理いろんなオブジェクトから同じデータを使える
主な用途キャラクターや処理の実装設定・共有データの管理

ScriptableObject・static・JSONの違いと使い分け

項目ScriptableObjectstaticJSON
エディタで直接編集
アセットとして管理
実行時の変更を保存
セーブデータ向き
データ共有のしやすさ
主な用途設定・共有データ一時的な共有値セーブデータ保存

実践的な使い方3選

キャラステータス管理

キャラクターの基本能力値をアセット化することで、プレイヤーも敵も同じ設計で扱えます。

using UnityEngine;

[CreateAssetMenu(fileName = "CharacterData", menuName = "Game/CharacterData")]
public class CharacterData : ScriptableObject
{
    public string characterName;
    public int hp;
    public int attack;
    public float moveSpeed;
}

設計をさらに綺麗にしたい場合は、オブジェクト指向の考え方と組み合わせると効果的です。

ゲーム設定値の一元管理

例えば以下のようなバランス調整用データも適しています。

  • 移動速度倍率
  • ステージ制限時間
  • ダメージ倍率

これらを1つのScriptableObjectにまとめることで、ゲームバランス調整が容易になります。

イベントチャンネル設計(上級)

ScriptableObjectは「イベントの仲介役」としても使えます。

例えば、プレイヤーがダメージを受けたときにUIへ通知する場合:

using UnityEngine;
using System;

[CreateAssetMenu(menuName = "Event/DamageEventChannel")]
public class DamageEventChannel : ScriptableObject
{
    public Action<int> OnDamageEvent;

    public void RaiseEvent(int damage)
    {
        OnDamageEvent?.Invoke(damage);
    }
}

このようにイベント用アセットを作ることで、

  • PlayerはUIを知らない
  • UIはPlayerを知らない

という「疎結合な設計」が可能になります。

ハッキング耐性の話

よくある疑問:

JSONは暗号化できるけど、ScriptableObjectは危険では?

結論

ビルド後はどちらも安全ではありません。

理由

  • JSON → 解析可能なファイル
  • ScriptableObject → ビルド内のデータ

どちらも「クライアント側」にある以上、
本気で解析すれば改ざん可能です。

よくある誤解

「ScriptableObjectは見えやすいから危険」
→ ビルド後は普通にデータ扱いです。

「JSONは暗号化すれば安全」
→ 復号ロジックがアプリ内にあるなら意味がない。

まとめ

ScriptableObjectは

  • データ設計を整理できる
  • シーンをまたいで共有できる
  • ゲーム構造を綺麗に保てる

非常に強力な仕組みです。

ただし、「保存用の仕組み」ではありません。

セーブデータはJSON、重要データはサーバー管理。
役割を正しく理解することが、綺麗な設計への第一歩です。