ScriptableObjectを理解したかもしれない話
こんにちは! P&M Entertainmentです!
最近Unityから離れていたのですが、不思議なもので、そのような状況で逆に理解できなかった概念がある日突然ピンと理解できたりするものです。
特に、数学を勉強していた方にはそういう経験があるのではないでしょうか。わたしは数学というか算数レベルで苦手だったので、このような経験は専らゲームプログラミングにおいて体験していますが。
ScriptableObjectという概念がUnityにあります。
わたしのゲーム製作の原点のひとつがRPGツクールです(もうひとつはHSPです)。
そんなわたしが、Unityを触った時に感じた疑問はふたつ。様々な枝葉のイベントから呼び出される共通のコモンイベントをどうやって実装すればいいのか、もうひとつはデータベースに該当するものはどうやって実装すればいいのか、です。
前者に関しては、和尚本で解決しました。GameManagerというシーンを管理する空のオブジェクトを用意するのが定石のようです。実際問題、Unityでは「GameManager」という名前を付けたオブジェクトはアイコンが特殊なものに変化します。そして、枝葉のオブジェクトは、Start()やAwake()のタイミングでこのオブジェクトを参照するわけです。
そして、後者の疑問に答えるのがまさにScriptableObjectだったわけなのです。
なんのことはない、ScriptableObjectはC#スクリプトで設計して、C#でデータ型を指定する不変のデータベースなのです。
ScriptableObjectのメリットとして、無数のキャラクターを生成する際のメモリ節約、という説明がなされます。
具体的な例で説明すると、例えばゾンビという敵キャラをゲーム中に出すとしましょう。
多くのゲームでは、パラメータに不変の値と、可変の値があります。この概念は、Wolf RPG エディターで顕著です。
ゾンビの例で考えましょう。ゾンビには、HP、攻撃力、防御力の3つのパラメータがあるとします。
この内、HPは最大HPと現在HPのふたつに別れます。HPはゲーム中変動する値だからです。これに対して、攻撃力と防御力は変動しないものとします。
この場合、ゾンビのパラメータをゾンビ自身のスクリプトコンポーネントで指定するとします。すると、無数のゾンビのオブジェクトを生成した場合、例えばゾンビ1体のデータが1KBだと仮定すると、ゾンビ1000体なら1000KB=1MBになります。
1MBならかわいいものですが、複雑なゲームならゾンビ1体当たりのデータ量も多くなるでしょう。また、敵キャラもゾンビだけとは限りません。
なぜこのような現象が起きるのかを考えてみましょう。それは、プログラムは正直なので、ゾンビ1体目の持つデータと、ゾンビ2体目の持つデータの中に共通の型と値があったとしても、それを別個のものと考えて記憶するためです。
我々人間は、共通するものはまとめて覚えてしまいます。
例えば、ゲームに登場する敵キャラがゾンビ、デビル、ウルフだとしましょう。そして、これらのキャラの弱点属性が、ゾンビは光、デビルも光、ウルフは火だったとすると、多くの人は「ウルフの弱点は火、それ以外は光」というようにまとめて覚えると思います。
つまり、Unityに「これは共通するデータだよ」と教えてあげる方法がまさにScriptableObjectなのです。
なぜなら、ScriptableObjectはアセットとして保存されます。アセットは、全てのオブジェクトから共通に参照されます。つまり、ゲーム上にいくらゾンビを生成しても、全てのゾンビはひとつのアセットを参照するからです。
そして、ScriptableObjectを活用すべきであるもうひとつの理由があります。それは、「RPGなどの製作に欠かせないデータベースなどを、よりUnityらしく、つまり、視覚的にマウスで作成することができる」ということです。
プログラムが本業ではない人にとって、Unityのメリットのひとつはほとんどの作業がGUIでマウスをポチポチすることで完結することです。
ScriptableObjectを使用しなくても、インスペクタで視覚的にパラメータの設定はできますが、初期値等はコードにハードコーディング(直書き)したりしています。
以上が、わたしが理解したScriptableObjectの概念です。
これで、Unityでデータベースを使用するのに、わざわざ使いやすさのわからないアセットを導入する必要がなくなりますし、RPG的な大量のデータを要するゲームも作れるという道が開けました。