【Unity】RPGを作るチュートリアルその15 戦闘画面の構成を考える回

【Unity】RPGを作るチュートリアルその15 戦闘画面の構成を考える回

シンプルなRPGをUnityで作るチュートリアルシリーズの15回目です。

第14回では敵キャラクターの定義データに、行動パターンを設定できる項目を追加しました。行動パターンについては条件に応じて選択されるように実装しました。

定義データに関しては一旦作業が完了したので、今回からはひとつ目の大きな山である戦闘関連の機能の実装に入っていきます。まずは戦闘画面でどのようにゲームオブジェクトを用意していくか、構成を考えていきましょう。

 

 

制作環境

MacBook Pro 2023 Apple M2 Max

Unity6 (6000.0.30f1) Silicon

 

作業内容と順序

シンプルなRPGを作る上でどんな作業が必要か、どんな順番で作っていくと良さそうか、別ページで検討しました。基本的にこの流れに沿って進めていきます。

 

チュートリアルの一覧

このシリーズ全体の一覧は以下のページにまとめています。

 

前回の内容

前回は敵キャラクターの行動パターンの機能を実装しました。

 

戦闘画面をどう実装するか

戦闘画面をどのように実装するのか考えておきましょう。戦闘用のシーンを作成するのか、移動用のシーン内で戦闘用のゲームオブジェクトを用意するのか、といった部分を決めておきたいと思います。

戦闘用のシーンを作成する場合、背景用のゲームオブジェクトやUIなど、ひとつのシーン内で扱うことができるので調整がしやすくなります。例えば炎の洞窟、雪山など、シチュエーションに合わせた背景オブジェクトを用意して、エンカウントした場所によって切り替えることができます。シーン自体は1つで、背景オブジェクトはPrefabで切り替えるのも良いかと思います。

戦闘が始まった時にシーン自体を切り替えると、切り替え時のロード時間が長くなるため、シーンの追加ロードが良いかもしれません。特にフィールドが広大だと再ロードに時間がとてもかかるので、なるべくロードし直すことは避けたいところ。

移動用のシーン内で戦闘用のゲームオブジェクトを用意するケースでは、シーン内で戦闘用ゲームオブジェクトの親オブジェクトを作っておいて、戦闘が始まる時に有効にする形です。同じシーン内にあるので追加ロードが必要なく、待ち時間という意味では減らせるのではと思います。同じシーン内にあるので、キー操作の制御はしっかりとしておきましょう。また、同じシーン内にある場合、戦闘で使うゲームオブジェクト数が多かったりメモリをたくさん使う場合には負荷が大きくなります。近年だと移動して敵に近づくとシームレスに戦闘が始まるケースもよく見られます。

今回のチュートリアルでは、後者の移動用のシーン内で戦闘用のゲームオブジェクトを用意する方式で進めたいと思います。2Dの戦闘で背景オブジェクトも負荷が少ないことが予想されるので、ゲーム起動時に読み込んでしまいます。2Dか、3Dかによってメモリにロードするデータ量も変わってくるため、作りたいゲームに合わせて選択すると良いでしょう。戦闘機能を詳細に作り込んでいく前に、モック版の段階で両方試してみるのも良いかと思います。

 

親オブジェクトの作成

戦闘に関する機能をまとめた親オブジェクトを作成していきます。シーン内で編集すると複数人でいじるのが大変になるので、戦闘関連の機能についてはPrefab化してPrefabの編集画面でいじっていくとやりやすくなるかと思います。

まずはHierarchyウィンドウから空のゲームオブジェクトを作成しましょう。名前は [BattleParent] にしました。

親オブジェクトの作成
親オブジェクトの作成

 

作成したゲームオブジェクトを選択した状態で、InspectorウィンドウからTransformの値をリセットします。親オブジェクトとして使うため、位置が子オブジェクトに影響しないようにしておきます。

値をリセットするのだポッター
値をリセットするのだポッター

 

このゲームオブジェクトに関しては忘れないうちにPrefabにしておきます。Prefabの保存先フォルダをまだ作っていなかったので、Projectウィンドウから「Assets」に移動して、新規フォルダを作成します。名前は [Prefabs] にしました。

Prefabを保存するフォルダを作成
Prefabを保存するフォルダを作成

 

作成した「Prefabs」のフォルダに移動して、Hierarchyウィンドウの「BattleParent」のゲームオブジェクトをProjectウィンドウにドラッグ&ドロップしてPrefabファイルを作成します。名前は変更せずそのまま使います。

Prefabの作成
Prefabの作成

 

作成したPrefabをダブルクリックしてPrefabの編集画面を開いておきます。UIなどはここから配置していきましょう。

Prefabの編集画面
Prefabの編集画面

 

戦闘画面の構成

今回のチュートリアルで作りたい戦闘画面のイメージとしては、ファミコン時代のドラクエ1やスーパーファミコン時代のドラクエ5のように、フィールド画面は背景としてそのまま表示しつつ、その上に戦闘画面のパーツが表示される形式です。ただ戦闘の背景画像まで作ると大変なので、敵キャラクターのスプライトが表示される領域についてはドラクエ2, 3, 4のように黒塗りにします。

戦闘画面で必要なパーツ構成を考えてみると、以下のものが必要になりそうです。

  • スプライトの表示領域
    • 背景
    • 敵キャラクター
  • UIの表示エリア
    • コマンド入力
    • 敵キャラクターの名前
    • 操作キャラクターのHP/MP
    • メッセージ表示
  • 管理用のゲームオブジェクト

移動用のフィールド画面より手前にスプライトを表示するため、Sorting Layerを追加します。戦闘用のスプライトの背景、戦闘用のスプライトの2つは必要そうです。敵キャラクターをスプライトで表示するか、Canvas上のImageで表示するかは更新頻度に応じて選択するとグッド。Canvas内の要素の一部が変更されるとそのCanvas全体が更新されるので、敵キャラクターのアニメーションなどがある場合はスプライトにしておいた方が良いかと思います。と言いつつ今回のチュートリアルでは敵キャラクターのアニメーションは入れませんが、拡張性を考えてスプライトとして描画したいと思います。

UIに関しては、コマンド入力用のエリア、敵キャラクターの名前を表示するエリア、操作キャラクターのHP/MPを表示するエリア、メッセージを表示するエリアなど、ドラクエを参考にしつつちょっとアレンジして配置していきます。これらのパーツについては戦闘画面用にCanvasを作成してその中で描画していきます。UnityのCanvasの更新の仕組みを考えると、それぞれCanvasを分けた方が更新頻度を減らせるのですが、今回のチュートリアルではそこまで厳密なパフォーマンスチューニングは行わないので同じCanvasに入れます。

管理用のゲームオブジェクトに関しては、「Game」のシーンと同じように「Managers」といった形で親オブジェクトを作成して、その中に必要なゲームオブジェクトを入れていきます。基本的には戦闘画面全体を管理するクラスを用意して、処理の内容に応じて別のクラスを呼び出す形になりそうです。対応するUIのパーツごとに管理する範囲を区切ってクラス分けしていこうと思います。操作キャラクターのHP/MPの表示を管理するクラス、コマンド入力を検知するクラス、といった感じです。

これらを踏まえて、準備作業を行なっていきます。

 

スプライト関係の準備

スプライトに関する親オブジェクトの作成と、Sorting Layerの追加を行います。

 

親オブジェクトの作成

Hierarchyウィンドウにて、Prefabの編集を行なっている状態で「BattleParent」の下に空のゲームオブジェクトを作成します。名前は [Sprites] にしました。

スプライト用の親オブジェクト
スプライト用の親オブジェクト

 

背景の親オブジェクト、敵キャラクターのスプライトの親オブジェクトについても作っておきましょう。作成した「Sprites」のゲームオブジェクトの下に、空のゲームオブジェクトを2つ作成し、それぞれ [Background][Enemies] と命名しました。

各パーツの親オブジェクト
各パーツの親オブジェクト

 

「Background」の下には背景画像1つを配置する予定です。「Enemies」の下には戦う相手の敵キャラクターのゲームオブジェクトを配置していきます。

 

Sorting Layerの追加

続いてSorting Layerを追加していきましょう。画面上部のメニューバーから [Edit] -> [Project Settings …] を選択し、「Project Settings」のウィンドウを表示します。左側のタブ領域から [Tags and Layers] を選択して「Tags and Layers」の画面を表示します。表示した画面で、「Sorting Layers」のリストにて [+] ボタンから2つ項目を追加し、それぞれ [BattleBackground][BattleCharacter] にリネームします。

Sorting Layerの追加
Sorting Layerの追加

 

フィールド画面における一番手前のレイヤーの「TilemapOverlay」よりも後ろの要素にすることで、戦闘関連のスプライトが画面手前に表示されるようになります。

 

手前に表示されるかどうかの確認

念の為設定がうまくいっているか確認してみましょう。

「Background」のゲームオブジェクトの下に、背景用のスプライトを作成します。Hierarchyウィンドウでコンテキストメニューを開き、[2D Object] -> [Sprites] -> [Square] から四角のスプライトを作成します。

背景用スプライトの作成
背景用スプライトの作成

 

作成したスプライトでは、Transformの値を以下のように変更しました。今は確認の段階なので直接位置を変えています。スプライトなので、戦闘が始まるタイミングでカメラの位置を読み取って、親オブジェクトである「Sprites」の位置を変更するように後程処理を入れたいと思います。Prefabの編集画面を表示している場合、Prefabでの編集を保存することでシーン内に変更が反映されます。

「Color」の項目は [#161616] にして完全な黒ではなく灰色に、「Sorting Layer」の項目は先ほど作成した [BattleBackground] にしています。

背景用スプライトの設定
背景用スプライトの設定

 

Prefabの設定を保存して、「Game」ウィンドウで以下のように表示されていればOKです。フィールド用の画像で一番手前にあるのは屋根のタイルですが、それよりも手前に戦闘用背景が表示されます。

戦闘用背景がフィールドの画像より手前にある
戦闘用背景がフィールドの画像より手前にある

 

敵キャラクターの画像についても配置してみましょう。先ほど編集していた「Square」のゲームオブジェクトを複製して、「Enemies」の下に移動させます。複製したゲームオブジェクトの名前は [Slime] に変更しました。

ゲームオブジェクトの複製
ゲームオブジェクトの複製

 

Inspectorウィンドウから設定を変更しましょう。Transformの「Scale」はそれぞれ [1] に変更しました。「SpriteRenderer」のコンポーネントでは「Color」の項目を [#FFFFFF] の白に、「Sorting Layer」の項目は [BattleCharacter] にしています。

敵キャラクターの設定
敵キャラクターの設定

 

設定を変更したらPrefabの編集内容を保存して、以下のように、戦闘用背景の手前に敵キャラクターが表示されればOKです。

背景の手前に敵キャラクター
背景の手前に敵キャラクター

 

これでスプライト部分の表示はいけそうですね。上でも少し触れましたが、スプライトなのでカメラの位置が動くと表示もずれてしまいます。そのため、戦闘突入時のスプライトの位置移動は課題として残しておきます。

 

今回のブランチ

 

まとめ

今回は戦闘関連の機能について、その実装方針を決めていきました。シーンは分けず、同じシーン内で戦闘用のパーツを実装していくことにして、その中のスプライトに関する表示機能を実装しました。

次回は戦闘画面のUI部分についてモック版として組んでいきましょう。

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!