本投稿は2024年9月時点の内容になります。アップデートにより変更となる場合があります。また環境によって違いがあると思いますのであくまで参考として、ご了承ください。
様々な書籍、ブログや動画を参考にさせていただきました。多すぎて一つ一つは紹介できませんが感謝です。
初心者の自分がUnity ソフトウエアでゲームを作ってみました。とりあえずシンプルなものということでモグラたたきに挑戦です。ゲーム作ってみるかという感じになったときに、いいタイミングで某ゲームのイベントシナリオ内ミニゲームにモグラたたきが実装されていたのでUIとかエフェクトとか、諸々の仕様をぱくって参考にして作ってみましたよ。様々なHowToの中の選択肢のひとつとして、同じ初心者さんの参考になればよいです。
\ チェック /
目次
データベース的な使用が便利なScriptableObjectを使ってみる
いろいろな種類の敵キャラクター、装備やアイテム、多様な魔法。これらを実装するのにデータベースがあったらいいですよね。そのような時の方法の一つがScriptableObjectです。便利で使いどころも多そうなので使ってみました。
本記事のポイント
- ScriptableObjectとは
- ScriptableObjectを実装してみます
- 実際にゲームオブジェクトから参照して使ってみる
\ 前回をチェック!今回の元になるクラスです。 /
ScriptableObjectってなに?
ScriptableObject は、クラスのインスタンスとは独立した大量のデータを保存するためのデータコンテナです。ScriptableObject の主な使用例の 1 つに、値のコピーを避けてプロジェクトのメモリ使用量を減らすことがあります。
Unityユーザーマニュアル
よくわかりませんね。なので今回もざっくりイメージ解説です。
ScriptableObjectとは
- どうやらデータ保存に特化したデータを扱うのが得意なオブジェクトのようだ
- 同じクラスのインスタンスを複数作る(同じゲームオブジェクトを大量生産する)際に個々にデータそのものを持たせずScriptableObjectの参照先(データのある住所)を持たすことでメモリーの使用量を削減することができる
なんとなくイメージ沸きましたか?
他にもアセットに保存されるのでデータの差し替えなど共通データの管理が便利(ゲームオブジェクトの画像を差し替える感じでデータの差し替えができる)だったり、シリアライズ可能で実行中インスペクター上から変更したデータはアセットに保存されるので調整などに使えるといったメリットがあります。まとめると
ScriptableObjectのメリット
- メモリの節約
- アセットとして共通データの管理がしやすい
- シリアライズできるてインスペクター上で値の編集や調整がしやすい
ScriptableObject追記
- ちなみにエディターでの編集の保存、アセットととして保存したデータの利用はできますが、ビルドされたゲームのデータを保存するのには使えないそうなので、データセーブには使えないようです。
- 基本的には変化しない定数を持たせるのがベターです。
ScriptableObjectを使ってキャラクターのデータベースを作る
データベースを実装するスクリプト
スクリプトを作成してみよう
- プロジェクトでスクリプト「UnitStatusDB」を作成。
- 「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;
}
スクリプトざっくり解説
- (16-25)MonoBehaviourクラス非継承の「UnitStatusData」クラスを定義。
- (14)[System.Serializable]はMonoBehaviourクラス非継承クラスのpublicフィールドをシリアライズ可能にしてインスペクターで編集可能にする属性です。
- (3-8)ScriptableObject継承した「UnitStatusDB」クラスを定義。「UnitStatusData」型を要素に持ったListをインスタンス化します。
- (2)[CreateAssetMenu]はUnity エディタの作成メニューに項目を追加する属性です。
データベースを作ってみよう
データベースを作成してみよう
- プロジェクトでフォルダー「ScriptableObjects」を作成。
- フォルダー「ScriptableObjects」内で右クリック>作成>「UnitStatusDB」をクリック
- ScriptableObjectを作成したら名前は任意で 今回「CharacterStatusDB」にしました
- ScriptableObject「CharacterStatusDB」をクリックして開いたインスペクターで「UnitStatusList」をクリック
- 「+」マークをクリック
- 各項目に値を入力します。名前:「Unitychan」、Atk:「1」、Def:「0」、MaxHp:「1」、Exp:「750」、UnitType:「Enemy」としました。
- さらに追加したいときは「+」マークをクリックします。
これでデータベースして登録できました。
実際にゲームオブジェクトにデータベースのデータを反映させよう
オブジェクトの名前と同じ名前のデータを取得できるようにする
- 「UnitStatusDB」クラスにデータベース検索用のメソッドを追加します。
- そのデータをEnemyStatusに反映するように、「Enemy」クラスにフィールド「characterStatusDB」を追加して、Setupメソッドを変更します。
- インスペクターから「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」クラスの追加部分を解説
- (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」クラスの変更点をざっくり解説
- (5)フィールドcharacterStatusDBを追加します。
- (10)GetStatusByNameでデータベースを検索して取得します。
- (12-18)取得したデータをゲームオブジェクトに反映させます。
インスペクターから「characterStatusDB」フィールドに対応するScriptableObjectをアタッチします。
ゲーム再生してコンソールに正しい値が出力されていればOKです。
addressablesというUnity パッケージを使用するとさらに便利になるようなので、興味ある方はぜひ。
まとめ
まとめ
- ScriptableObjectは簡単にデータベースを作成できる方法の一つなので、ぜひ一度使ってみましょう。
- 基本的に変化のない定数を持たせよう
\ Unityのスクリプトを書くのに役立ちます /
もっと早く教えてほしかった!Unity C#入門
MARU
おすすめ記事
Unity ソフトウエアでゲーム制作#1モグラたたき編(28.ゲームに効果音…
Unity ソフトウエアでゲーム制作#1モグラたたき編(27.エフェクト2パ…
Unity ソフトウエアでゲーム制作#1モグラたたき編(26.エフェクトその1)
Unity ソフトウエアでゲーム制作#1モグラたたき編(25.プレハブバリア…
Unity ソフトウエアでゲーム制作#1モグラたたき編(24.Buttonで…
Unity ソフトウエアでゲーム制作#1モグラたたき編(23.シンプルなアニ…