【Unity】ScriptableObjectの作り方・使い方

ScriptableObjectを使いこなそう ゲーム開発

Unityでゲームを作っていると、特にRPGなどで大量のデータを扱う必要が出てきて「データの管理が大変だからデータベース的なものが欲しいなぁ」と思うことがあります。

そんなときに便利なのがUnity標準の「ScriptableObject」という機能なのですが、正直なところ「そんなの初めて聞いた」とか「なんか聞いたことはあるけど使い方がよく分からん!」という方は多いのではないでしょうか。

そこでここではScriptableObjectについて作り方や使い方を説明していきますね。

ScriptableObjectとは?

でははじめに、そもそもScriptableObjectとは何なのか?という話をします。

ScriptableObjectは基本的にゲーム中に変化しない値を登録しておくのに使うデータベースのようなものです。例えば敵キャラクターの最大HPやアイテムの得点などはゲーム中に変化することがあまりないですよね。ScriptableObjectはそういったデータを格納しておき、必要な時に読み込んで使う場合に便利です。

ScriptableObjectを使うメリット

次にScriptableObjectを使うことで得られる主なメリットは次の5つがあります。

  1. メモリを節約できる
  2. パラメータをインスペクター上で簡単に管理できる
  3. 簡単に作ったり使ったりできる
  4. Unityエディタ上でゲームを再生しているときに値を変更できる
  5. どのシーンからでも参照することができる

メモリを節約できる

まずScriptableObjectを使うメリットとして一番大きいのが、メモリの節約になるということだと思います。

これはどういうことか?例えば次のような敵キャラクターのプレハブがあるとしましょう。

スライム(プレハブ)
最大HP 100
攻撃力 10

そしてこのスライムのインスタンスを作るとすると、当然パラメータは次のようになります。

スライム(インスタンス)
最大HP 100
攻撃力 10

当たり前ですが「スライム(インスタンス)」のパラメータは元のプレハブと同じですね。ところが両者は全く同じパラメータではありますが、各インスタンスのパラメータは別々に扱われるため、インスタンスを作った分だけメモリを食ってしまうのです。

普通にプレハブをインスタンス化した場合

そこでScriptableObjectが役立ちます。ScriptableObjectを使えば共通の値を読み込んで使えるので、余計にパラメータを作る必要がなくなってメモリを節約できるというわけです。

ScriptableObjectを使った場合

パラメータをインスペクター上で簡単に管理できる

2つ目のメリットは、ScriptableObjectはインスペクター上で簡単に値を変更したり管理したりできる点です。

一つ目のメリットのように、単にデータを外部に切り分けるというとJSONなどが思い浮かびますが、例えばJSONの場合はUnity用のファイルではないのでインスペクターから直接変更することはできません。しかしScriptableObjectを使えばインスペクター上にフォームが表示されるので直接パラメータの値を変更することができます。

簡単に作ったり使ったりできる

3つ目のメリットは、ScriptableObjectは簡単に作ったり使ったりできるということです。具体的にどのように作ったり使ったりするかはこの後説明していきますね。

Unityエディタ上でゲームを再生しているときに値を変更できる

4つ目のメリットは、ScriptableObjectはUnityエディタ上でゲームを再生している最中に値を変更でき、(エディタ上で)変更した値は再生終了後も保持されることです。これによってデバッグが楽になりますし、再生中にちょっと値を調整したいといった場合に非常に便利です。

ただしビルド後はエディタ上とは違った挙動をするため、ScriptableObjectをセーブデータの記録用として使うことはできません

どのシーンからでも参照することができる

最後に5つ目のメリットはScriptableObjectはどのシーンのゲームオブジェクトからでも参照することができる点です。ScriptableObjectはゲームオブジェクトではないのでシーンに依存しません。

この性質を利用すれば、例えばゲーム中で「シーンをまたいで保持したい値」がある場合にそれをScriptableObjectに入れておくことで楽に扱うことができます。ちなみにこの方法は「DontDestroyOnLoadとstatic変数を併用する方法」よりも安全であり、しかもインスペクターで値を確認できる等のメリットもあります。

ScriptableObjectの作り方

それではScriptableObjectの具体的な作り方を見ていきましょう。手順は次の通りです。

  1. ScriptableObjectクラスを継承したクラスを作る
  2. プロジェクトビューからScriptableObjectファイルを作成する

手順1:ScriptableObjectクラスを継承したクラスを作る

まず、ScriptableObjectを作るためにはScriptableObjectクラスを継承したクラスを作成し、必要なパラメータをそのクラスに書いておく必要があります。具体的には次のようなコードになります。

using UnityEngine;

[CreateAssetMenu]
public class TestScriptableObject : ScriptableObject
{

    [SerializeField]
    string testString = "これはScriptableObjectのテストです。";

    public string TestString { get { return testString; } }

}

ScriptableObjectを単純なデータコンテナとして利用する場合はその値を他のC#スクリプトから変更する必要はないので、外部から参照できるプロパティにはgetterだけを書いておくことが多いです(※ただし一時的に値を保持させてシーン間で使いまわすといった場合はその限りではありません)。

手順2:プロジェクトビューからScriptableObjectファイルを作成する

さてスクリプトを用意出来たらあとはファイルを作るだけです。先述の例ならプロジェクトビューの適当なフォルダで右クリックすると「TestScriptableObject」ファイルを作成するメニューが出るようになるので、それを選んで新しいScriptableObjectファイルを作成しましょう。

ScriptableObjectの使い方

最後はScriptableObjectの使い方についてです。まずScriptableObjectファイルはインスペクターから登録可能なので、シリアラライズ可能な変数を作っておけばインスペクターにそれ用の登録欄が出てきます。

したがって、先ほどの例であれば

  1. 適当なC#スクリプトにTestScriptableObject型の変数を作る
  2. インスペクターからTestScriptableObjectを登録しておく
  3. C#スクリプトで手順1の変数にアクセスする

といった手順で使うことができます。

おわりに

以上、ScriptableObjectの作り方や使い方についてご説明しました。

ScriptableObjectは初めのうちは分かりにくい機能だと思いますが、使いこなせるようになると非常に便利なのでUnityでゲームを作っているとそのうち絶対に手放せなくなると思います。ぜひ今回の内容を参考にしていただき、ゲーム開発にお役立ていただければ幸いです。