ゲーム制作   Unity ソフトウエア 

Unity ソフトウエアでゲーム制作#1モグラたたき編(6.ScriptableObject)

キャッチ画像モグラたたきScriptableObject

本投稿は2024年9月時点の内容になります。アップデートにより変更となる場合があります。また環境によって違いがあると思いますのであくまで参考として、ご了承ください。

様々な書籍、ブログや動画を参考にさせていただきました。多すぎて一つ一つは紹介できませんが感謝です。

初心者の自分がUnity ソフトウエアでゲームを作ってみました。とりあえずシンプルなものということでモグラたたきに挑戦です。ゲーム作ってみるかという感じになったときに、いいタイミングで某ゲームのイベントシナリオ内ミニゲームにモグラたたきが実装されていたのでUIとかエフェクトとか、諸々の仕様をぱくって参考にして作ってみましたよ。様々なHowToの中の選択肢のひとつとして、同じ初心者さんの参考になればよいです。

\ チェック /

データベース的な使用が便利なScriptableObjectを使ってみる

いろいろな種類の敵キャラクター、装備やアイテム、多様な魔法。これらを実装するのにデータベースがあったらいいですよね。そのような時の方法の一つがScriptableObjectです。便利で使いどころも多そうなので使ってみました。

本記事のポイント

  • ScriptableObjectとは
  • ScriptableObjectを実装してみます
  • 実際にゲームオブジェクトから参照して使ってみる

\ 前回をチェック!今回の元になるクラスです。 /

前回はキャラクターのクラスを作りました。

ScriptableObjectってなに?

ScriptableObject は、クラスのインスタンスとは独立した大量のデータを保存するためのデータコンテナです。ScriptableObject の主な使用例の 1 つに、値のコピーを避けてプロジェクトのメモリ使用量を減らすことがあります。

Unityユーザーマニュアル

よくわかりませんね。なので今回もざっくりイメージ解説です。

ScriptableObjectとは

  1. どうやらデータ保存に特化したデータを扱うのが得意なオブジェクトのようだ
  2. 同じクラスのインスタンスを複数作る(同じゲームオブジェクトを大量生産する)際に個々にデータそのものを持たせずScriptableObjectの参照先(データのある住所)を持たすことでメモリーの使用量を削減することができる

なんとなくイメージ沸きましたか?

他にもアセットに保存されるのでデータの差し替えなど共通データの管理が便利(ゲームオブジェクトの画像を差し替える感じでデータの差し替えができる)だったり、シリアライズ可能で実行中インスペクター上から変更したデータはアセットに保存されるので調整などに使えるといったメリットがあります。まとめると

ScriptableObjectのメリット

  • メモリの節約
  • アセットとして共通データの管理がしやすい
  • シリアライズできるてインスペクター上で値の編集や調整がしやすい

ScriptableObject追記

  1. ちなみにエディターでの編集の保存、アセットととして保存したデータの利用はできますが、ビルドされたゲームのデータを保存するのには使えないそうなので、データセーブには使えないようです。
  2. 基本的には変化しない定数を持たせるのがベターです。

ScriptableObjectを使ってキャラクターのデータベースを作る

データベースを実装するスクリプト

スクリプトを作成してみよう

  1. プロジェクトでスクリプト「UnitStatusDB」を作成。
  2. 「using UnityEngine;」以下に下記のようにコーディングしました。
//Unity エディタの作成メニューに項目を追加する属性です
[CreateAssetMenu]
public class UnitStatusDB : ScriptableObject
{
    //UnitStatusDataを要素に持つListをインスタンス化
    public List<UnitStatusData> UnitStatusList = new List<UnitStatusData>();

}

//以下のクラスがシリアライズ可能であるという属性
//MonoBehaviourクラスでないピュアクラスにつけることで
//MonoBehaviour継承クラスから参照した際にpublicなフィールドが
//インスペクターで編集可能になります
[System.Serializable]
//データベースに必要なパラメタをまとめたUnitStatusDataクラスを定義
public class UnitStatusData
{
    //メンバ変数
    public string name;
    public int atk;
    public int def;
    public int maxHp;
    public int exp;
    public UnitType unitType;
}

スクリプトざっくり解説

  1. (16-25)MonoBehaviourクラス非継承の「UnitStatusData」クラスを定義。
  2. (14)[System.Serializable]はMonoBehaviourクラス非継承クラスのpublicフィールドをシリアライズ可能にしてインスペクターで編集可能にする属性です。
  3. (3-8)ScriptableObject継承した「UnitStatusDB」クラスを定義。「UnitStatusData」型を要素に持ったListをインスタンス化します。
  4. (2)[CreateAssetMenu]はUnity エディタの作成メニューに項目を追加する属性です。

データベースを作ってみよう

データベースを作成してみよう

  1. プロジェクトでフォルダー「ScriptableObjects」を作成。
  2. フォルダー「ScriptableObjects」内で右クリック>作成>「UnitStatusDB」をクリック
  3. ScriptableObjectを作成したら名前は任意で 今回「CharacterStatusDB」にしました
  4. ScriptableObject「CharacterStatusDB」をクリックして開いたインスペクターで「UnitStatusList」をクリック
  5. 「+」マークをクリック
  6. 各項目に値を入力します。名前:「Unitychan」、Atk:「1」、Def:「0」、MaxHp:「1」、Exp:「750」、UnitType:「Enemy」としました。
  7. さらに追加したいときは「+」マークをクリックします。

これでデータベースして登録できました。

実際にゲームオブジェクトにデータベースのデータを反映させよう

オブジェクトの名前と同じ名前のデータを取得できるようにする

  1. 「UnitStatusDB」クラスにデータベース検索用のメソッドを追加します。
  2. そのデータをEnemyStatusに反映するように、「Enemy」クラスにフィールド「characterStatusDB」を追加して、Setupメソッドを変更します。
  3. インスペクターから「characterStatusDB」フィールドに対応するScriptableObjectをアサインします。
public class UnitStatusDB: ScriptableObject
{ 
    //UnitStatusDataを要素に持つListをインスタンス化
    public List<UnitStatusData> UnitStatusList=new List<UnitStatusData>();
    //以下追加
    public UnitStatusData GetStatusByName(string name)
    {
        //UnitStatusDataのフィールドnameと引数nameが一致するデータをresultに代入
        var result=UnitStatusList.Find(UnitStatusData => UnitStatusData.name == name);

        //一致するものがなかったらコンソールに出力
        if(result == null)
        {
            Debug.Log("指定された名前がステータスリストに見当たりません");
        }
        //resultを返します
        return result;

    }
}

「UnitStatusDB」クラスの追加部分を解説

  1. (6-19)引数nameと名前が一致するUnitStatusDataを返すメソッドGetStatusByNameを定義
public class Enemy : MonoBehaviour
{
    public EnemyStatus enemyStatus {  get; set; }

    [SerializeField] UnitStatusDB characterStatusDB;
    public void Setup()
    {
        //GameObjectと同じ名前のステータスを検索
        UnitStatusData unitStatusData = characterStatusDB.GetStatusByName(this.name);
        //各パラメータの設定
        string name = unitStatusData.name;
        int atk = unitStatusData.atk;
        int def = unitStatusData.def;
        int level = 1;
        int maxHp = unitStatusData.maxHp;
        int exp = unitStatusData.exp;
        UnitType unitType = unitStatusData.unitType;
        //新しいインスタンスを作成
        enemyStatus = new EnemyStatus(name, atk, def, level, maxHp, exp, unitType);
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
    
    }

    private void OnEnable()
    {
        //enemyを設定
        Setup();
    }

}

「Enemy」クラスの変更点をざっくり解説

  1. (5)フィールドcharacterStatusDBを追加します。
  2. (10)GetStatusByNameでデータベースを検索して取得します。
  3. (12-18)取得したデータをゲームオブジェクトに反映させます。

インスペクターから「characterStatusDB」フィールドに対応するScriptableObjectをアタッチします。

ゲーム再生してコンソールに正しい値が出力されていればOKです。

addressablesというUnity パッケージを使用するとさらに便利になるようなので、興味ある方はぜひ。

まとめ

まとめ

  • ScriptableObjectは簡単にデータベースを作成できる方法の一つなので、ぜひ一度使ってみましょう。
  • 基本的に変化のない定数を持たせよう
ユニティちゃん公式ホームページへ
ユニティちゃん公式ホームページ
ユニティちゃんライセンス
ユニティちゃんの画像、素材、ライセンスロゴはユニティちゃんライセンス条項を元に使用しています

\ Unityのスクリプトを書くのに役立ちます /

もっと早く教えてほしかった!Unity C#入門

MARU

マケイヌ的おすすめ度

わかりやすい度

目指せ脱初心者

〇おすすめポイント

ボリューム大でC#学習にもよく使う関数のチェックにもOK

×よくないポイント

始めたばかりの人にはちょっと難しい

おすすめ記事

 

プロフィール

マケイヌ

人生のメインストリームから外れた40代の♂。

90年代オルタナにはまり、文字通りメインストリームから逸脱。 その後もたびたび人生から逃亡。

心が動いた作品の紹介や 自分のちいさな経験、HowToを発信できればと日々模索中。

1年後までにイラストと写真のポートフォリオをつくりたい。

記:2019年12月

▼プロフィールはこちら

Follow me

アーカイヴ