ScriptableObject はスクリプトインスタンスから独立した大量の共有データを格納できるクラスです。SerializedObject と混同しがちですが、こちらはエディタークラスであり、目的も違うものです。例えば 百万の配列をもつスクリプトでプレハブ作ったとします。配列は 4 MB のメモリを占有し、プレハブがオーナーとなります。プレハブをインスタンス化するごとに、その配列が複製されます。ゲームオブジェクトを 10 個作成した場合、10 インスタンス合計で 40 MB の配列no データとなります。
すべてのプリミティブ型、文字列、配列、リスト、Unity に特有の Vector 3 などの型や、カスタムクラスを Unity は serialize 属性により宣言されたオブジェクトに属する複製としてシリアライズします。例えば SerializableObject を作成して integer が 1 万個だけ格納した場合、配列はそのインスタンスに格納されます。インスタンスは個別のデータのオーナーとして扱われます。ScriptableObject のフィールドや任意の UnityEngine.Object フィールドである MonoBehaviour、Mesh、GameObject 等は値でなく参照が格納されます。ScriptableObject は配列を格納します。ScriptableObject への参照があるプレハブのインスタンスが 10 個あり、4 MB のデータを保有する場合、合計はあくまで 4 MB となり前例のように 40 MB とはなりません。
ScriptableObject を使用する場面は、値の複製をさけることでメモリ消費を節約するときですが、プラグ可能なデータセットを定義することにも使用できます。例をあげると RPG における NPC キャラクターのショップです。例えばカスタムの ShopContents ScriptableObject で複数のアセットを作成して、それぞれで購入可能なアイテムを定義できます。ゲームに 3 つのゾーンがあると仮定すると、それぞれのゾーンで異なるレベルのアイテムを提供できます。ショップのスクリプトの中で ShopContents オブジェクトを参照して利用可能なアイテムを定義できます。サンプルについてはスクリプトリファレンスを参照してください。
ScriptableObject 派生のクラスに付けることのできる CreateAssetMenu によって簡単にカスタムアセットを作成することができます。
Tips: インスペクター上で ScriptableObject からの参照を扱う場合、参照フィールドをダブルクリックして ScriptableObject を開きます。またカスタムのエディターを作成して、その型が表すデータが管理しやすいようにインスペクターの外見を定義できます。