Unity公式のe-bookでScriptableObjectへの理解が進んだとは言え、モヤモヤは残っていました。結局、ScriptableObjectって何なのか、と。しかし、遂に自分なりの答えを見つけることが出来たのでここに記します。
ScriptableObjectとは、アセット化することのできる特殊なインスタンスである。
まず先にオブジェクト指向プログラミングにおけるクラスとインスタンスについて再確認します。
OOPにおけるクラス、インスタンス
クラスとはデータ構造と振る舞い(メソッド)をまとめる、データタイプの設計図でインスタンスはそこから生み出された実体です。クラスそれだけではプログラムは動かず、実行中にそこからインスタンスが生成され、それらが実働することによってデータが処理されます。
この時、インスタンスはメモリ上に生成されるのでプログラムが終了すれば当然消えてしまいます。
インスタンスはそれぞれ固有のパラメータを持つことの出来る個体であり、例えばHumanクラスがあったとして、あるインスタンスは日本人で男かもしれませんし、他のインスタンスはアメリカ人の女性かもしれません。
つまりクラスとは(複雑な)データタイプの原型であり、インスタンスはそれを元に生み出される個々のオブジェクトということです。
UnityのPrefab
ここでUnityの重要な機能のひとつであるPrefabに目を向けたいと思います。Prefabとはシーンのヒエラルキー上で作ったGameObject(ゲームオブジェクト)をアセット化する機能です。
GameObjectとはまさしくUnityにおける個の存在を定義する単位であり、オブジェクトです。様々なコンポーネントを追加したり、別のGameObjectをネストすることでデータ構造や振る舞いを設計することができます。
しかし、そのままだとUnityシーン上でしか存在できない儚いオブジェクトです。そこで利用するのがPrefab機能であり、シーン上のGameObjectをAssetsフォルダ内(あるいはその下階層の特定フォルダ)にドラッグ&ドロップするとアセット化できます。
これにより、Prefabとしてある存在の原型をアセットとしてプロジェクト内に保有することが可能となり、あらゆるシーンでそのPrefabから生成されるGameObjectを再利用することができるようになります。
前述のクラスとインスタンスの関係からすると、Unityのプレハブはインスタンスから逆にクラスを作り出すような機能と考えられるのではないでしょうか。
ScriptableObjectクラスとインスタンス
というわけで、いよいよ本題です!ScriptableObjectを使おうと思ったらまずC#スクリプトを作成することになります。これはつまりScriptableObjectクラスを継承したクラスの設計なんですよね。そのクラスがどんなデータを持っているかを書きます。だから、この時点ではScriptableObjectは存在しませんし、プロジェクト内には、ただのC#スクリプト・アセットがあるだけです。
ScriptableObjectクラスにCreateAssetMenuアトリビュートを付けると、右クリックのCreateメニューからそのクラスで定義したScriptableObjectを作成できるようになります。作成するとScriptableObjectがプロジェクト上に生成されます。これはいくつでも作ることが出来て、それぞれに固有のパラメータを入力し保存することが出来ます。アセットなので、Unityエディターを終了しても消えません。
つまり、これって消えないインスタンスなのでは?と思ったのです。ScriptableObjectはデータコンテナとしての使い方が主であり、例えば敵のデータやアイテムのデータを定義し、アセットとして保存してそれをGameObjectが参照することが出来ます。
しかし、ScriptableObjectはメソッドを持つことも出来、単純なデータ保存アセットではありません。じゃあ一体何なのかって話だったわけですが、一応自分の中ではこのような一定の答えが出てきたので納得は出来ました。そういう風に考えたらメチャクチャ便利な機能ですよね。
まとめ
というわけで、簡単にですがScriptableObjectについての考察を書いてみました。分かったようで分からず悩んでいたのですが、アセット化できる特殊なインスタンス及び、特殊なクラスによってアセット化されたインスタンスである、と考えればこんなに素晴らしい機能はないだろう、と気づくことが出来ました。