現場レベルのゲーム制作が、すべてここで学べます。
この記事は3Dダンジョン探索型RPGの作り方講座の第2回目です。
前回はプロジェクトの作成を含め、ゲーム制作を開始するための基本的な準備を行いました。
前回の記事:

今回からダンジョン要素の実装に着手していきます。
戦闘やキャラクタークリエイト機能などはダンジョンをある程度完成させてから順次取り掛かっていきます。
Unityで作る3Dダンジョンの仕様と特徴について
今回作成するダンジョン探索システムの基本的な仕様や特徴は以下の通りです。
これから作り上げるダンジョンマップや拡張エディタの仕様
ダンジョンのマップを視覚的に分かりやすく作成するためにマップエディタを作成します。
基本機能
- Unity Editor拡張による専用マップエディタウィンドウ
- 20×20マスのマップ編集
- ScriptableObjectを使ったマップデータのファイル保存
- 床と壁のタイルをマウスクリック・ドラッグ操作でペイント
- タイル配置とオブジェクト配置のモード切り替え
マップオブジェクト配置機能
- 11種類のオブジェクト(Entityとも呼称)配置
- ExitPoint(ダンジョン出口)
- Up_Stairs/Down_Stairs(階段)
- Treasure(宝箱)
- Gathering(採集ポイント)
- FOE(固定敵)
- Locked_Door/KeyofDoor(扉と鍵)
- Conveyor(強制移動床)
- WarpPoint(ワープポイント)
- Spikes(ダメージ床)
オブジェクト詳細設定
- オブジェクト名による詳細指定(移動先座標、方向など)
- オブジェクトIDによる関連付け(テーブル番号、方向指定など)
- 選択したオブジェクトの詳細編集機能
データ管理機能
- マップ名とエネミーレベルの設定
- ダンジョン進入時の初期位置・方向設定
- 採集ポイント、エネミーテーブル、FOEテーブルの管理
- 一意なファイル名での自動保存
ScriptableObjectとは マップデータや敵のデータなどを管理
今回、マップデータを作成するにあたり、Unityの機能の一つであるScriptableObjectを使用していきます。
今後、マップデータに限らずアイテムデータや敵のデータなど、多くのデータ定義にこの仕組みを用いるので、今のうちに覚えておきましょう。
なお、C#に関する基礎部分の解説は今回の講座では省略しています。解説をお求めの方は以下のカテゴリの記事を参考にしてください。

ScriptableObjectの概要
ScriptableObjectはUnityが提供するデータコンテナです。通常のC#クラスやMonoBehaviourと違い、アセットとして保存できるので、プロジェクト内でデータを”使い回し”できます。
以下は敵のステータスを定義する場合のスクリプトです。(例示なので作成する必要はありません)
|
1 2 3 4 5 6 7 8 9 |
using UnityEngine; [CreateAssetMenu(fileName = "EnemyStatus", menuName = "Dungeon/EnemyStatus")] public class EnemyStatusSO : ScriptableObject { public string enemyName; public int maxHP; public float moveSpeed; } |
上記のように定義すると、ProjectビューのCreateメニューからEnemyStatusアセットが作成可能になります。

作成したアセットはInspectorからパラメータを設定できるようになり、また他のスクリプトからこのアセットのパラメータを取得することができます。
なお後述しますが、このゲームでのマップデータ作成においてはInspectorでの編集は行いません。
ScriptableObjectの特徴と利点
-
アセット化
作成されたScriptableObjectはゲームオブジェクトではなくアセットとして扱われます。Hierarchyに配置する必要がなく、プロジェクトフォルダ内にファイルとして存在します。 -
Inspector編集
生成したアセットはInspectorで自由に値を設定できます。シーンに依存せず、どの場面でも同じデータを共有可能です。 -
データとロジックの分離
デザイナーがInspectorで数値を調整でき、プログラマーはコードに集中できます。 -
再利用性
一度作成したアセットを複数のシーンやオブジェクトで共有可能。重複定義が不要になります。 -
メモリ効率
シーン間で同じインスタンスを参照するため、不要になったらGC(ガベージコレクション)によって簡潔に管理できます。 -
ホットリロード対応
ゲーム実行中にInspectorの値を変更すると、値が即時反映されるのでデバッグが捗ります。
難しい説明もありますが、とにかく「前もって作成しておくデータの管理に便利」という認識で問題ありません。
(逆に言えばゲーム中にスクリプト上で生成・管理されるデータはScriptableObjectにする必要はありません)
マップデータScriptableObjectクラスの作成
それではマップデータの入れ物であるScriptableObject用のC#クラスを実装していきます。
ProjectビューからC#ファイルの作成を行います。対象フォルダは“Assets/Scripts”以下です。定義を行うスクリプトになるので、役割でフォルダを細分化する場合はDefinesフォルダを作成してその中でスクリプト作成を行うと良いでしょう。
該当フォルダを開いたら右クリック→[Create]→[MonoBehaviour Script]でC#スクリプトを作成できます。クラス名(ファイル名)はMapDataSOとします。

このファイルをダブルクリック等で開き、スクリプトエディタを立ち上げます。
まずは地形情報(床か壁か)を設定できるシステムを構築することを目標に進めていきます。
MapDataSO.cs
MapDataSO.csの中身を以下のようにします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
using UnityEngine; using System; using System.Collections.Generic; /// <summary> /// マップデータScriptableObject定義クラス /// </summary> [CreateAssetMenu (fileName = "MapDataSO", menuName = "Dungeon/MapDataSO")] public class MapDataSO : ScriptableObject { // マップ内の全タイル情報リスト(20×20個のデータ) public List<TileData> tiles = new List<TileData> (); } // タイルの種類定義(列挙型) [Serializable] public enum TileType { Wall, // 壁タイル Ground, // 床タイル } // 各タイルの情報定義クラス [Serializable] public class TileData { public int tileX; // このタイルの位置(X方向) public int tileY; // このタイルの位置(Y方向) public TileType type; // このタイルの種類 // コンストラクタ public TileData (int tileX, int tileY, TileType type) { this.tileX = tileX; this.tileY = tileY; this.type = type; } } |
今後このデータを他クラスから参照する場合に備え、タイルの種類の情報なども含めて定義しています。
以下はスクリプトの各箇所の簡単な解説です。
MapDataSOクラス
C#クラスをScriptableObjectとして宣言することで、前述の機能が使えるようになります。
フィールド(変数)として、そのマップ内の全てのタイル情報を1つのリストで扱うため、tilesを宣言しています。
このゲームは初期の頃のウィザードリィなどと同様に1マップを20×20のタイルで構成しているため、tilesリストの要素数は20×20で400にして使います。
拡張性も考えて明示的に20や400とおいう数値はこの段階では入れていません。
タイルの種類定義(TileType)
列挙型(enum)を使用して各タイルの種類を定義しています。
壁タイル(Wall)と床タイル(Ground)の2種類を使います。
TileDataクラス
MapDataSOのtilesリストで400個作られるタイルデータについて、それぞれの情報を扱うクラスです。
タイルがある位置(X方向とY方向)、およびタイルの種類をこのクラスに含めています。
マップエディタ機能をエディタ拡張で実装する
以上で最低限必要になるマップデータの入れ物はできましたが、これを実際にScriptableObjectとして作成して手入力する場合は以下のような画面になります。
試しにプロジェクトフォルダで右クリック > Create > Dungeon > MapDataSOで作成してみてください。

全400あるタイルの1つ1つを順番に数値入力していくというのは作業量が多すぎて非現実的です。見た目にもわかりにくいです。
そこで、ここからはUnityのEditor拡張を駆使して、グラフィカルにタイルの配置を行えるようなマップエディタ機能を作っていきましょう。
Editor拡張とは
UnityのEditor拡張とはUnityエディタの見た目や機能をカスタマイズする技術のことです。
Inspectorビューに表示される内容をわかりやすく改善したり、独自のウィンドウを作って新機能を実装することもできます。
また、パラメータの編集をわかりやすくできるため、チーム開発の際にもメリットが大きいです。(プログラマーとそれ以外で担当を分けやすい)
Editor拡張のスクリプトは「Editor」という名前のフォルダ以下に配置した場合に有効です。まずはScriptsフォルダ以下にEditorフォルダを用意しましょう。

マップエディタスクリプト(MapEditorWindow.cs)
Editorフォルダ以下にMapEditorWindowスクリプトを新規作成します。
なお以下のコード入力直後はエラーが出ますが、続けて編集するスクリプトにて解消されます。(今後の章でも複数のスクリプトをまとめて編集することがあります)
まとめ

Editor拡張でマップエディタを作成し、壁か床かという地形データを表示する機能を実装できました。
まだこのダンジョンを操作によって探索できるようにはなっていないので、次の記事ではプレイヤーオブジェクトを作成して歩き回れるようにしていきます。
次の記事:

現場レベルのゲーム制作が、すべてここで学べます。






コメント