現場レベルのゲーム制作が、すべてここで学べます。
この講座では全12回でUnityを使ってUnity入門の森の「ノンフィールドRPG講座」で制作した”果て無きダンジョン”を改良アップデートしてSlay the Spire風のデッキ構築系オリジナルカードバトルJRPGを制作します。
ターン制コマンドバトルでダンジョンを進むシンプルなRPGを制作した前作の「ノンフィールドRPG講座」。ここからシンプルな設計を保ちつつ、最小限の修正で大きな仕様変化・ゲーム性の向上を実現させます。
ゲーム制作では一度作ったゲームをどんどんアップデートしてゲームを面白くしていくスキルはとても大切です。
今回の講座ではこうした一度作ったゲームをどうアップデートしていくかの流れも追体験できるようにしています。
講座ではUnityとC#を使って解説を丁寧に行っていきます。プログラミングにはまだ不慣れという初心者でも最後まで完成できるようになっています。
今回はその第1回目です。
制作するオリジナルRPGの仕様について
「ダンジョンを前進してエンカウントした敵と戦闘を繰り返しながらレベルを上げていき、食料がなくなるまでにどれだけダンジョンを進めるか」
というシンプルなノンフィールドRPGとして制作した”果て無きダンジョン”のバトルシステムを、今回はカードバトル制へ改良していきます。
↑こちらが前回の「ノンフィールドRPGの作り方講座」で完成させたゲームです。
アップデートして作り上げるゲームの新仕様は以下の通りです。
企画名・操作端末・想定プラットフォーム
ゲーム名:「果て無きダンジョン アドバンス」
ジャンル:デッキ構築型カードバトル式ノンフィールドRPG
対象プラットフォーム:縦持ちスマホ。
基本解像度:1080×1920
ゲームの流れ
タイトル→強化→ダンジョン→イベントの選択→カードやレリックの取得→カードバトル→ゲームオーバー
ゲーム内操作:ダンジョンシーン
前進:ダンジョンを進む。食料を消費する。右か左の進行方向を選択。戦闘・カード取得・回復・レリック取得などのイベントを選択してゲームを進める
休憩:HPを回復する。食料を消費する。
カード:現在のデッキ状態を確認する。保有カードの効果の確認も可能。
ゲーム内操作:戦闘シーン
カードバトル:毎ターン、スキルポイントを3保有し、所有しているカードからランダムで3枚のカードが配布される。
カードにはコストが設定されていて使用するとスキルポイントを消費する。
ターン終了ボタンをタッチすると敵のターンとなる。
HPもしくは食料が0になるとゲームオーバー。
バフ・デバフ効果やレリックによるパラメータ変化なども反映される。
コマンドバトルからカードバトルにシステムを変更。
これまでは全戦闘共通の「攻撃」、「防御」、「HP回復」の3コマンドしかありませんでした。
ですが、今回の応用編でカードバトルにすることで、より戦略的なバトルを楽しめるようになります。
ゲームオーバー処理
進んだフロアに応じてポイントを取得できる。
ポイントを持っていると、タイトル画面で初期レベルと初期食料を増やすことができます。
ここは前作と同じままです。
このゲームを制作する目的・目指すもの
Unityでオリジナルゲームを制作する上で役立つ数多くのスキルが手に入り、かつ読者がオリジナルRPGを作る汎用テンプレートのようなものを提供する。
シンプルな設計でわかりやすく、そして応用しやすいRPGの作り方の習得を目指す。
そしてゲームとしての面白さをグッと高めるアップデートを行う。
というわけで今回の講座はこのようなコンセプト・仕様で進めていきます。実際にこのようなゲームをどう作っていくのか。一緒に開発を体験していきましょう!
プロジェクトを開く
まずはUnity Hubを使って前作ノンフィールドRPG「果て無きダンジョン」のプロジェクトを開きます。
前作のプロジェクトファイルのダウンロードは以下の記事から行ってください。

この講座ではUnityのバージョンは「6000.3.****」を使用します。バージョンはある程度違っても問題はありません。
「果て無きダンジョン」を制作したときのバージョンは「6000.0.****」を使用していたため、エディタのバージョンを変更する必要があります。
エディタバージョンアップの流れもここで抑えておきましょう。
バージョン「6000.3.****」をインストールしたあと、Unity Hubのプロジェクトのリストから「果て無きダンジョン」のエディタバージョンを変更してからプロジェクトを開きます。

プロジェクトを起動しているあいだに、いくつか確認用のウィンドウが表示されます。

「Continue」をクリックします。
続いて「UnityのグラフィックAPIのデフォルトが変わります」という通知が表示されることがあります。

こちらも「Confirm」をクリックして進めます。
プロジェクトを開くことができたら、まずはカードや状態異常で使う画像を集めましょう。
Unity Asset Storeでゲーム制作に使う素材を集めよう
UnityのAsset Storeから以下のものを購入(無料)してダウンロードとインポートを行います。以下のリンクからUnityのAsset Storeを開きます。


右上のアカウントアイコンからUnity IDにログインします。
カードのアイコン素材
Asset Storeのサイトで以下の素材を検索します(もしくはリンクをクリックして開く)。
![]()
右側にある「マイアセットに追加する」をクリックします。

Unityに関連するサービスの利用規約への同意画面が表示されるので、問題がなければ「同意する」をクリックします。
ブラウザ上部にマイアセットに追加されたことが通知されるので「Unityで開く」をクリックします。

さらにブラウザがUnityエディタを開いていいか確認してきますので、「Unity Editor を開く」をクリックしてUnityエディタを開きます。
![]()
UnityエディタがアクティブになりPackage Managerが開き、マイアセットに追加したアセット[500 Free Skill Icons]が右側に表示されます。
マイアセットに追加したアセットはメニューの[My Assets]に表示されます。
Package Managerを閉じてしまったときはUnityエディタの[Window]→[Package Manager]で開くことができます。
右側にある[Download]ボタンをクリックして、アセットをダウンロードします。
![]()
ダウンロードが完了するとボタンが[Import *** to project]に変わるので、さらにクリックします。
(***はアセットのバージョンによって変わります)
![]()
インポートウィンドウが開くので[Import]をクリックします。
[Assets]フォルダの下にアセットのフォルダとファイルがインポートされます。これでプロジェクトへのアセットのインポートが完了します。アセットによっては容量が大きくダウンロードやインポートに時間がかかることがあります。
状態異常などのアイコン素材も準備しよう
同じ要領で以下のアセットもプロジェクトにインポートします。
ここまでのデータを集め終わると元のアセットフォルダに追加されてこのようになっているはずです。

今回インポートした素材のうち、2D Icons – Picto Icon Pack 01 は Layer Lab フォルダ内に保存されていました。
必要ファイルがあれば保存場所や保存形式は多少違っていてもOKです。
また、もし利用できる素材やアセットが変わっても基本的なインポートの流れなどは同じです。
マスターデータの作成:カードデータをScriptableObjectで実装する
まずは[Assets]→[Scenes]にある[Battle]をダブルクリックしてバトルシーンを開いておきます。
「攻撃」「防御」「回復」というコマンドをカードとして扱うように変更していきます。まずはカードのマスターデータを作成します。
まずはカードの基本情報となるCardParamsクラスを作成します。[Assets/Scripts]フォルダを右クリックし、[Create]→[Scripting]→[Empty C# Script]をクリックして、名前をCardParamsにします。
(ちなみに、[Scripting]→[MonoBehaviour Script]を選ぶとUnityが予め用意した機能を使うためのMonoBehaviourを継承します。[Empty C# Script]にするとUnity依存の機能を使わないソースコードになります)

CardParamsクラスを編集していきます。このゲームではカードのID、画像、コスト、名前、説明などをクラスの変数として持たせます。
この変数はここでは private(外から見えない)にしていますが、[SerializeField]をつけることでインスペクターでは見えるようにしています。
そして、外から読み取り専用で取得できるようにしています(「プロパティ」といいます)。
こうすることで、書き換えられる心配がない安全な設計になります。
CardParams.cs
このCardParamsはカード1枚分のデータを定義するクラスです。
以下のような内容のクラスにしてください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using UnityEngine; [System.Serializable] public class CardParams { [SerializeField] private string id;// カードを区別するための「識別子」 public string ID => id; [SerializeField] private Sprite cardSprite;// カードの画像 public Sprite CardSprite => cardSprite; [SerializeField] private int cost;// カードを使用するときに必要なSPのコスト public int Cost => cost; [SerializeField] private string cardName;// カードの名前 public string CardName => cardName; [SerializeField] private string cardDescription;// カードの説明 public string CardDescription => cardDescription; [SerializeField] private bool isReward;// 報酬の対象かどうか public bool IsReward => isReward; } |
最後に定義しているisReward変数は後にこのカードをイベントや戦闘終了時に出現させるかどうかを決めるためのものです。
True(インスペクター画面でチェックを入れる)であれば報酬カードとして出現するように後ほどゲームシステムを実装します。
[System.Serializable]について補足
class定義の前に[System.Serializable]が付与されています。これは対象となるクラス(今回はCardParamsクラス)をUnityがシリアライズ(データ化)できるようにするための宣言です。
具体的には以下の用途で使われます。
- インスペクターへの表示 → 別クラスのフィールドとして持ったとき、Inspectorに中身を展開して表示・編集できる
- セーブデータへの保存 → クラスのデータをファイルに書き出したり読み込んだりできる
- ネットワーク通信 → データを送受信する際にクラスをそのまま使える
インスペクターへの表示はあくまで副産物のひとつであり、「Unityや.NETがこのクラスをデータとして扱えるようにする」というのが本質的な役割。
ソースコードの内容を詳しく解説
ここからはCardParamsクラスの内容を詳しく解説します。
クラスの構造
このクラスは以下の6つの情報を持っています。
| フィールド | 型 | 意味 |
|---|---|---|
| id | string | カードを区別する識別子 |
| cardSprite | Sprite | カードの画像 |
| cost | int | 使用に必要なSPコスト |
| cardName | string | カードの名前 |
| cardDescription | string | カードの説明文 |
| isReward | bool | 報酬の対象かどうか |
フィールドとプロパティのセットについて
このクラスの書き方は全て同じパターンの繰り返しになっています。
|
1 2 |
[SerializeField] private int cost; // ① 実際のデータを持つ変数(private) public int Cost => cost; // ② 外部から読み取るための窓口(public) |
①のフィールド
- privateなのでクラスの外からは直接アクセスできない
- [SerializeField]によってInspectorには表示される
②のプロパティ
- =>は「この値を返す」という意味
- 以下と全く同じ動作をします
|
1 2 3 4 5 6 7 8 |
// 省略記法 public int Cost => cost; // 省略しない書き方 public int Cost { get { return cost; } } |
なぜこの書き方をするのか
「読むことはできるが、外から書き換えはできない」状態を作るためです。
|
1 2 3 4 |
// 外のクラスからアクセスした場合 card.Cost; // ✅ 読める card.cost; // ❌ privateなので見えない card.Cost = 3; // ❌ getterしかないので書き込めない |
データをprivateで隠しつつ、読み取り専用の窓口だけを公開することで意図しない書き換えを防ぐことができます。これをカプセル化と呼びます。
データ定義をする際に今回のような書き方はよく出てくるので慣れておきましょう。
複数のカードをまとめて管理するためのクラスを作ろう
次に、先ほど作成したカード1つの定義を行ったCardParamsクラスを使い、複数のカードをまとめて扱うクラスを作ります。
[Assets/Scripts]フォルダを右クリックし、[Create]→[Scripting]→[ScriptableObject Script]をクリックして、名前をCardDataにします。
CardDataクラスに先ほど作成したCardParamsクラスをListで変数cardListとして宣言しておきます。
このcardListの中から画像と名前と説明、そしてコストを取得するメソッドを追加します。
つまりカードのデータベースを作成していくことになります。
まとめ

新しい素材のインポートとカードのデータベースの作成を行いました。
次回からはスクリプトを変更してバトルをコマンドバトルからカードバトルに変更していきます。
次の記事:

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







コメント