有意義なサイト作りのためJavaScriptを使ってます。ご了承ください。

Unityでゲーム制作日記1 - ScriptableObject覚書

 ·  ☕ 5 分で読めます

やっとUnityでゲーム作り始めました!
今まで腰にモーニングスターでもついてんのかってほど腰が重かった私ですが、やっとこさ楽しいゾーンに入ったのでこのまま突っ走りたいです。楽しく苦しみたいと思います。
ということでUnityの覚書をここに殴り書くことにしました。なるべく伝わるように書いていきたいので参考になれば幸いです。

ということで最初のお題はScriptableObjectです。「クラスとメソッドと返り値あたりまではなんとかわかる」レベルの私が最初につまづき挫折したポイントなのでここから備忘録をつけていきます。
なお以上の経緯ですので「メソッドと返り値、SerializeFieldによる紐付けあたりまでは何となく理解できてる」ぐらいの人を想定して書いています。そこがおぼつかない方は他の講座で予習をお願いします。この辺までは無料でも講座が転がっているはずです。

ScriptableObject is 「ほかのオブジェクトにデータを入れられるクラス」

なんのこっちゃなのでもうちょっと解説すると、要は**特定オブジェクトに紐づかないデータ(マスターデータなど)**格納に使われるクラスとそのインスタンスのことです。
Unityでオブジェクトを使うときにはUnityEngineの下にいるObjectクラスを継承したクラス、例えばObject->Component->Behaviour->MonoBehaviourと継承しているスクリプトをアタッチしています。
ですがゲームオブジェクトにアタッチさせたくないデータ、たとえば敵キャラやアイテムなどのパラメータなど複数オブジェクトで使いまわしたいようなデータはアセット化した方が良かったりします。その場合に活躍するのがScriptableObjectです。

Object->ScriptableObject

こんな感じの継承関係です。

メリット

1つは軽量なことです。
オブジェクトごとにパラメータを設定すると同じパラメータを設定していてもその数だけメモリを使用します。これをScriptableObjectを生成して定義すればそこをオブジェクトに見に行かせるだけでいいのでメモリの節約になります。
たとえば敵キャラデータだと、HPなんかは個別に持つ必要があっても攻撃力や守備力、特殊能力なんかは同じ種類の敵なら使いまわせるわけです。べんり。

こう使うッ

まずScriptableObject生成スクリプトを書きます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "MyScript/CreateStoryText")] // 生成メニュー追加

public class State : ScriptableObject // ScriptableObject使用の準備
{
    [SerializeField] private string storytext; // データ格納場所

    public string GetText() // 格納データを返すメソッド
    {
        return text; 
    }
}

Class宣言の前にエディタに拡張メニュー追加用のAttributeを書きます。パス管理もできます。自作メニューはまとめるといい感じ。
その後にScriptableObjectを継承して使いたいパラメータを定義。この例ではSerializeFieldをつけてGetText()というメソッドで格納データを渡す構造にしてますが、スクリプトからの書き換えは一切使わないならpublic変数を直接書いちゃってもかまいません。どちらでもエディタから直接値をいじれます。かがくの ちから です!

あとは保存しエディタに戻ってコンパイル。
右クリック->Create内に作ったメニューがあるのでそこから作成。無事にさっきのスクリプトに書いたフィールドに書き込めるオブジェクトが生成されたでしょうか?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StoryController : MonoBehaviour 
{
    private State state; // ScriptableObject継承

    void Start()
    {
        Debug.Log(state.GetStateStory()); // ScriptableObjectからメソッドを呼び出す
    }
}

もういっちょスクリプトを書きます。
さっきのScriptableObject->Stateクラスを継承したインスタンスを作り、そこからメソッドを呼び出します。
好きなテキストを入れてデバッグコンソールに表示して遊んでみましょう。ド長文出力も想いのまま。やったぜ。

バランス調整にも便利

参考サイト様曰く、

このScriptableObject、実はテストプレイ中にも値を変更できるんです。
通常、MonoBehaviourを継承したスクリプトでInspectorに表示しているフィールドは、Unityエディタでゲームを実行中に値を変えても、ゲームを終了した時に元の値に戻ります。これはこれで便利なのですが、新しい値を保持したい時でもゲーム終了後に改めて入れ直す必要があるのでちょっと面倒。
しかしScriptableObjectの値は、Unityエディタでゲームを実行中にInspectorから変更したら、ゲームを終了させてもそのままになっています。Unityエディタで値を変えた場合には、アセットファイルの内容も書き換えてくれるんです。

とのことです。要するにマスターデータを格納しておけばプレイしながらいじれるわけです。チームでのバランス調整にこれ以上ない頼もしい機能…だと思います1
RPGやシミュレーションはバランスが命なので覚えておくといいです。便利な世の中になったものよのう。
一方でセーブ用途では使えません。実機でScriptableObjectの値はいじれないからです。セーブは他の手段で実装しましょう。

まとめ

ということでマスターデータ管理に便利なScriptableObject、やっと理解できた話でした。継承とメソッドの概念をうまく飲み込めてなかったみたいですね…精進。
雑な説明で申し訳ありません。もしわからなければ下段参考サイト様、およびそのまた参考サイト様もご参照あれ。とってもわかりやすく書かれています。
やっとUnity使い第一歩を踏み出せました。これからArbor・Odin・UniTask・宴・の三種の神器(4つ)でもっと上を目指したいです。がんばるぞー!

参考


  1. 実務未経験につき大規模制作がどんな感じかわからないのでこんな言い方になっています ↩︎

シェアはこちら:

ふらもん
書いた人:
ふらもん
ゲームクリエイター見習い。リンクは別館の制作・攻略サイト