【Unity】ScriptableObjectで関連するフィールドをまとめる方法

【Unity】ScriptableObjectで関連するフィールドをまとめる方法

ScriptableObjectを使ってデータ格納用のクラスを作ることがあります。……あるよね?(不安)

その際、フィールドをいくつか作ることになるかと思いますが、これをカテゴリごとにうまくグループ化して表示したいなーと思い立ったのでその方法をメモ。

 

環境

macOS 10.14 Mojave

Unity2018.2.20f1

ScriptableObjectについて

ScriptableObjectはマスタデータなどの共有データを格納するのによく使われるクラス。使い方次第ではかなり広い用途があるクラスです。

このブログでもScriptableObjectについて概要と作り方、マスタデータを格納する場合のメリット・デメリットを扱っているのでこちらもぜひ。

今回はこのScriptableObjectにフィールドを作ってデータを持たせる際、ひとまとめにしたいフィールドのグループを作る方法を扱います。

グループ化って?

ScriptableObjectのフィールドのグループ化って何のこと? と思う方もいるかもしれないので、もう実物を見てもらいます。

通常、ScriptableObjectを継承したスクリプトを書く際は、以下のようにフィールドが並ぶことになるかと思います。

フィールドがずらり
フィールドがずらり

 

これでも悪くないのですが、どうせなら似たようなグループのフィールドはまとめたい……。

カテゴリでまとめる
カテゴリでまとめる

 

敵の管理情報に関してはEnemyInfo、戦闘シーンで使うパラメータについてはEnemyParam、戦闘後の経験値やドロップアイテムはEnemyReward、みたいな感じで分かれていると設定値を眺めるときに内容を把握しやすいですよね。これを実現する方法をメモしておきたかったんです。

やり方

まずはScriptableObjectを継承したスクリプトを作成します。

グループ分けしていない状態のスクリプトはこんな感じ。

スクリプトの中で使う分にはこれだけでもいいのですが、Inspectorウィンドウからバランス調整したいときに変更する対象のパラメータが分かりやすい方が嬉しいんです。

それを解決する方法は2つ。

ひとつは[Header]のAttributeを使ってInspectorウィンドウでヘッダを表示する方法。

もうひとつは[System.Serializable]を使ってシリアライズ対象のクラスを用意し、パラメータのカテゴリごとにクラスを分ける方法です。

[Header]のAttributeを使う方法はこのブログでも触れたのでそちらを見ていただくとして、ここでは[System.Serializable]を使う方法を考えます。

ScriptableObjectはオブジェクトの中身をアセットファイルとして保存(=シリアライズ)します。シリアライズの対象となるフィールドやクラスについてはいくつかの条件がありますが、今回導入する独自のクラスによるデータ保存を行う場合は[System.Serializable]を使ってシリアライズ対象クラスであることを宣言します。

上のスクリプトを書き換えてみると以下のようになります。

EnemyInfo、EnemyParam、EnemyRewardの3つのクラスを作成し、それぞれに[System.Serializable]のAttributeを付けました。「using System;」を書いている場合は[Serializable]だけでも大丈夫です。

ScriptableObjectを継承したクラスの中でこの新しい3つのクラスをフィールドとして用意します。

この状態で保存してコンパイルを通せば、以下のようにクラスごとに分かれた形で表示されます。

カテゴリでまとめる
カテゴリでまとめる

 

デバッグ時に値を変更する場合も、戦闘中であればEnemyParamの中をいじればいいですし、経験値を増やしたいなーとなったらEnemyRewardの中をいじればOKと、変更する場所もちょっとだけ分かりやすくなるメリットがあります。

また、スクリプトの中からこのScriptableObjectの値を利用する場合も、enemyParam.atkのようにカテゴリごとにアクセスすることができます。この辺は好みが分かれるところですが、個人的にはカテゴリごとにまとまってる方が好きです。インテリセンスでフィールドがズラーっと並ぶとちょっとビビるタイプなので。

他にもメリットとして、カテゴリの使い回しをしやすい点もあります。雑魚敵にはこのカテゴリはいらないけど、ボスにはこのカテゴリを表示させたい、でもこの辺は共通で使いたい、なんてときに[System.Serializable]を付けたクラスを好きなように組み合わせられます。

まとめ

ScriptableObjectの中で関連するフィールドごとにまとめたいときには[System.Serializable]を付けたクラスを用意して使うと便利です。

特に威力を発揮するのがデバッグ時。バランス調整でScriptableObjectの値を変える場合に、どこを変えたらいいか分かりやすくなります。

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!