現場レベルのゲーム制作が、すべてここで学べます。
この講座では3Dダンジョン探索型RPGの作り方について説明しています。今回はその第4回目になります。
前回はプレイヤーオブジェクトとミニマップを実装し、自由にダンジョン内を探索できるようになりました。
前回の記事:

ダンジョンシステムの開発はここで一旦後回しにし、もう一つこのゲームで根幹となるシステムである戦闘について実装を進めていきます。
今回はUnity入門の森初の多人数パーティーVS多人数パーティーの戦闘を扱います。
ウィザードリィや世界樹の迷宮シリーズのように前衛と後衛が存在し、かつFF10のようなカウントタイムバトル形式を採用した本格的な戦闘システムです。
他のRPG講座でも1対1や1対多人数の戦闘システムは作っていますが、こちらのパーティーが自由に編成できる形での戦闘システムも開発できれば鬼に金棒です。
本格的な戦闘システムの実装に一緒にチャレンジしていきましょう!
- 複数キャラの戦闘シーンの作成
- 戦闘シーンのUI作成 前衛と後衛のパーティー編成に対応させる
- (Image)背景画像オブジェクト BackGroundの作成
- (Empty)前衛アクター表示領域 ActorUIArea_Vanguardの作成
- (Empty)後衛アクター表示領域 ActorUIArea_Rearguardの作成
- (Empty)カウントタイムUI表示領域 CountTimeUIAreaの作成
- (Empty)エネミーUI領域 EnemyUIAreaの作成
- (Empty)戦闘コマンドUI領域 BattleCommandUIAreaの作成
- (Image)アクターUIの親 ActorUIの作成
- (Image – ActorUI)アクターアイコン画像 ActorIconの作成
- (TextMeshPro – ActorUI)アクター名テキスト ActorNameの作成
- (Image – ActorUI)アクターHPゲージ画像 HPGageの作成
- (TextMeshPro – ActorUI)アクター名テキスト HPLogoの作成
- (TextMeshPro – ActorUI)アクター残りHPテキスト HPTextの作成
- (Image – ActorUI)アクターTPゲージ画像 TPGageの作成
- (TextMeshPro – ActorUI)”TP”ロゴテキスト TPLogoの作成
- (TextMeshPro – ActorUI)アクター残りTPテキスト TPTextの作成
- ActorUIオブジェクトをPrefab化・複製
- (Button)バトルコマンドUI BattleCommandUIの作成
- BattleCommandUIオブジェクトをPrefab化・複製
- EnemyUIオブジェクトの作成とPrefab化
- 戦闘シーン用のスクリプトを仮作成
- ActorUI.cs (新規)
複数キャラの戦闘シーンの作成
シーン(Scene)とは
Unityにおける「シーン」とは、ゲームを構成する各場面をまとめた「部屋」のようなものだと考えられます。
例えばゲームのタイトル画面、実際にキャラクターを操作するダンジョン探索画面や戦闘画面など、それぞれの状況で表示されるものや動くものが異なることがあります。
これらの場面ごとに必要なゲームオブジェクト(キャラクターや背景、UIなど)や、それらにアタッチされたスクリプト、カメラ、ライトといった要素がすべてシーン(Scene)の中に保存されています。
シーンで区切った開発を行うことでゲーム全体の要素が管理しやすくなります。特にチーム開発においては各役職の人間が作業分担を行え、効率的になります。
ここまではプロジェクトを立ち上げた時に1つ用意されているサンプルシーンを改造する形で開発を進めてきましたが、ここからは戦闘画面という別の場面の開発に移ります。よって、新しくシーンを作成していきましょう。
シーンの新規作成
新しいシーンを1から作成する場合はエディタ画面左上のFileメニューから[New Scene]をクリックします。

シーンのテンプレート(初期設定)を選ぶ画面が表示されますが、特に変更せずCreateボタンを押下します。

まだ何もオブジェクトを配置していない状態ですが、一旦このシーンを保存しておきます。
Fileメニューから[Save As…]ボタンを押下し名前を付けて保存します。場所は Assets/Scenes 以下に、シーン名はBattleとします。

既存シーンの名称変更
前回まで開発していたダンジョン探索シーンについても、初期シーン名であるSampleSceneの状態から変更しておきます。
Projectビュー上でSampleSceneとなっている名前欄をダブルクリックし、Dungeonに名称変更します。

シーン名はスクリプトで参照する場合があるので適したものを付けるようにしていきましょう。
戦闘シーンの画面構成について
Battleシーンを開いている状態を確認したら戦闘画面のレイアウト作成に入ります。
今回作るゲームでは戦闘画面に映るオブジェクトは全てUIによって構成していきます。
前回の章で画像表示にImageコンポーネントを使用しましたが、今回は文章表示を行うTextコンポーネント(具体的にはTextMeshPro)も織り交ぜます。
戦闘システムについては後にも触れますが、味方キャラクターはアクター(Actor)、敵キャラクターはエネミー(Enemy)と呼称していきます。
アクターについては前衛に最大3人、後衛に最大3人を表示するのでそれをふまえた構成を考えます。
戦闘シーンのUI作成 前衛と後衛のパーティー編成に対応させる
最初はUIを配置・作成するためにCanvasオブジェクトから用意していきます。
前回と同様の設定で作成します。Canvas Scalerコンポーネントのパラメータを忘れずに変更しておきましょう。

Dungeonシーンからのコピーでも問題ありません。
以降は必要になるUIオブジェクトを順番に作成していきます。
UIオブジェクトの作成・編集時にはHierarchyビューでのオブジェクトの並び順に注意してください。
UI要素が重なった時は基本的に下側にあるオブジェクトの方が画面上で手前に表示されます。
(Image)背景画像オブジェクト BackGroundの作成
Canvas全体を薄く覆う黒めの単色画像、BackGroundオブジェクトを作成します。
- RectTransform:AnchorsをStrechにし、Left・Top・Right・Bottomを全て0
- Image – Source Image:Noneのまま
- Image – Color:黒っぽい灰色、Alpha値は半分ほど
AnchorsをStretchに設定し、Left・Top・Right・Bottomを全て0にすることで親であるCanvas全体に広がるように自動調整され、画面サイズが変わっても追従するようになります。

(Empty)前衛アクター表示領域 ActorUIArea_Vanguardの作成
前衛に属する最大3人のアクターUIを表示する領域となるオブジェクト、ActorUIArea_Vanguardを作成します。
このオブジェクト自体は処理や描画を行わないので空オブジェクトとして作成します。HierarchyビューでCanvasオブジェクトを右クリックし、[Create Empty]を押下すればOKです。
Canvas以下であれば空オブジェクトであっても自動的にTransformからRect Transformに切り替わります。
- Rect Transform:Anchorはbottom–center、Positionは(0, 162)、サイズは(1080, 104)

ここから暫くは、このように「〇〇要素を表示するUIの親となるオブジェクト」を続けて作成していきます。
同じような場所で表示するオブジェクトは1つの親にまとめることで、ローカル座標で相対的に位置調整が出来るのでレイアウトの管理がしやすくなり、スクリプト上で動的にオブジェクトを作成する場合にも扱いやすくなります。
(Empty)後衛アクター表示領域 ActorUIArea_Rearguardの作成
後衛に属する最大3人のアクターUIを表示する領域となるオブジェクト、ActorUIArea_Rearguardを作成します。
前衛表示領域オブジェクトと同様の設定なのでオブジェクトのコピー&ペーストから始めても構いません。Y座標のみ下に動かします。
- Rect Transform:Anchorはbottom–center、Positionは(0, 55)、サイズは(1080, 104)

(Empty)カウントタイムUI表示領域 CountTimeUIAreaの作成
このゲームの戦闘システムであるCTB(カウントタイムバトル)を実現するため、次にどのキャラクターにターンが周ってくるのかという順番を表示するUIである“カウントタイムUI”をのちほど作成します。
その表示領域として空のオブジェクト、CountTimeUIAreaを画面左上のあたりに作成します。
- Rect Transform:Anchorはtop-left、Positionは(60, -150)、サイズは(120, 300)

(Empty)エネミーUI領域 EnemyUIAreaの作成
エネミーのグラフィックを表示するUIの領域として、EnemyUIAreaを作成します。
エネミーUIは横に並べて配置するので横長のエリアを取りました。
- Rect Transform:Positionは(0, 100)、サイズは(800, 280)

(Empty)戦闘コマンドUI領域 BattleCommandUIAreaの作成
アクターのターン中に表示される、どの行動を行うかの選択肢となるボタンを表示する領域、BattleCommandUIAreaを画面右上のあたりに作成します。
- Rect Transform:Anchorはtop-right、Positionは(-100, -150)、サイズは(190, 300)

下準備はひとまずここで終了とします。次からは前衛・後衛アクター表示領域に実際に表示するUIオブジェクトを作成していきます。
(Image)アクターUIの親 ActorUIの作成
アクターひとり分の情報を表示するUI群の親オブジェクトおよび背景画像の表示として、ActorUIオブジェクトを作成します。これはActorUIArea_Vanguardオブジェクトの子として作成します。(Rearguardの方でも可)
ImageコンポーネントのSource Imageに対し、Projectビューから画像ファイルをドラッグ&ドロップする事で表示させる画像を指定できます。
- RectTransform:Positionは(0, 0)、サイズは(320, 104)
- Image – Source Image:Assets/Textures/GUIs/ActorWindow.png
なお画像UIのサイズ設定については、ImageコンポーネントにてSource Imageを指定した後に[Set Native Size]ボタンを押下する事で、その画像ファイルの元々のサイズと同じ値が自動的に入力されます。

以降のアクターUI関連のオブジェクトは、全てこのActorUIの子として作成します。
(Image – ActorUI)アクターアイコン画像 ActorIconの作成
アクターのアイコン(顔グラフィック)を表示するImageオブジェクト、ActorIconを作成します。
ここからTPTextオブジェクト作成までずっとActorUIオブジェクトの子に配置します。
- RectTransform:Positionは(-106, 26)、サイズは(96, 48)
- Image – Source Image:Noneのまま、あるいは任意のアイコン画像

(TextMeshPro – ActorUI)アクター名テキスト ActorNameの作成
アクターの名前をテキストとして表示するTextMeshProオブジェクト、ActorNameを作成します。
UnityのUI機能においてテキストの表示はTextMeshProというコンポーネントが行っています。オブジェクト作成時のメニュー欄での表示は[Text – TextMeshPro]ですのでこれを選択すればOKです。
TextMeshProの初回作成時には以下のようなウィンドウが立ち上がります。ここでは[Import TMP Essentials]をクリックする必要があります。暫く待てばインポートが自動的に終わるのでこのウィンドウを閉じます。

InspectorからTextMeshProコンポーネントを確認します。ここの上部に大きなテキストボックスがあるので、ここに入力した文章が画面に表示されます。
Font Assetパラメータには使用するTextMeshPro用フォントを指定します。
Font Sizeには文字サイズ、Vertex Colorには文字色、Alignmentには整列(中央揃えにするか等)の設定が可能です。
なおFont Sizeについては、その下にAuto Sizeというチェックボックスがあります。ここをONにすることで、表示できる枠に対し文字量が多かった場合に自動的にフォントサイズの調整を行ってくれるようになります。(サイズの下限や上限も設定できます。)
- RectTransform:Positionは(50, 24.5)、サイズは(208, 45)
- TextMeshPro – Text:空欄もしくは任意の文字列(スクリプトから変更します)
- TextMeshPro – Font Asset:Assets/Fonts/NotoSans_BlackShadow
- TextMeshPro – Font Size:Auto Sizeをオン、Auto Size Optionsの(Min, Max) = (10, 28)
- TextMeshPro – Alignment:中央揃え

(Image – ActorUI)アクターHPゲージ画像 HPGageの作成
アクターの残りHPをゲージで表示するImageオブジェクト、HPGageを作成します。
残りHPが減少していくにつれゲージの右側からだんだんと非表示になっていく描画を行います。そのためにImage TypeはFilledを選択します。
FilledになったImageオブジェクトは、スクリプトでfillAmountプロパティ(0.0~1.0)を変更するだけで簡単に表示範囲を変えられるようになります。
- RectTransform:Positionは(-78, -33.5)、サイズは(146, 21)
- Image – Source Image:Assets/Textures/GUIs/Gage_HP.png
- Image – Image Type:Filledを選択、Fill MethodはHorizontal、Fill OriginはLeft
Fill MethodをHorizontal、Fill OriginをLeftにすることで左から右へゲージが満たされ、減少時は右から縮むような表現が可能になります。

(TextMeshPro – ActorUI)アクター名テキスト HPLogoの作成
アクターのHPゲージ付近に”HP”という文字を表示するTextMeshProオブジェクト、HPLogoを作成します。
Material Presetを変更することで、同じフォントファイルでも異なった装飾(文字の影など)を適用することが可能です。今回はHP・TP表示に適した設定を用意しているのでこれを使用します。
- RectTransform:Positionは(-135, -15.2)、サイズは(32, 26)
- TextMeshPro – Text:HP
- TextMeshPro – Font Asset:Assets/Fonts/NotoSans_BlackShadow
- TextMeshPro – Material Preset:NotoSans_BlackShadow_HPTP
- TextMeshPro – Font Size:20
- TextMeshPro – Vertex Color:濃い目の橙色
- TextMeshPro – Alignment:中央揃え

(TextMeshPro – ActorUI)アクター残りHPテキスト HPTextの作成
アクターの残りHPを表示するTextMeshProオブジェクト、HPTextを作成します。
表示する文章はスクリプトで制御するため現在は設定不要ですが、見た目の確認用に100の数値で仮入力します。
文章入力の際にはRichText機能を使用することで、文章内の特定の文字だけ異なるサイズ/異なる色で表示したりなどが可能です。詳しくは公式のリファレンスを参照してください。もちろんスクリプト内からの入力でも反映されます。

- RectTransform:Positionは(-59, -11)、サイズは(110, 42)
- TextMeshPro – Text:100<size=60%><color=#222>/100</color></size>
- TextMeshPro – Font Asset:Assets/Fonts/NotoSans_BlackShadow
- TextMeshPro – Material Preset:NotoSans_BlackShadow_HPTP
- TextMeshPro – Font Size:Auto Sizeをオン、サイズは10~26
- TextMeshPro – Vertex Color:濃い目の橙色
- TextMeshPro – Spacing Options:Characterを8
- TextMeshPro – Alignment:右揃え

(Image – ActorUI)アクターTPゲージ画像 TPGageの作成
アクターの残りTPをゲージで表示するImageオブジェクト、TPGageを作成します。
HPゲージの設定と概ね同じですのでオブジェクトをコピーして調整するのが簡単です。
- RectTransform:Positionは(78, -33.5)、サイズは(146, 21)
- Image – Source Image:Assets/Textures/GUIs/Gage_TP.png
- Image – Image Type:Filledを選択、Fill MethodはHorizontal、Fill OriginはLeft

(TextMeshPro – ActorUI)”TP”ロゴテキスト TPLogoの作成
アクターのTPゲージ付近に”TP”という文字を表示するTextMeshProオブジェクト、TPLogoを作成します。HPLogoからのコピーが簡単です。
- RectTransform:Positionは(21, -15.2)、サイズは(32, 26)
- TextMeshPro – Text:TP
- TextMeshPro – Font Asset:Assets/Fonts/NotoSans_BlackShadow
- TextMeshPro – Material Preset:NotoSans_BlackShadow_HPTP
- TextMeshPro – Font Size:20
- TextMeshPro – Vertex Color:濃い目の青色
- TextMeshPro – Alignment:中央揃え

(TextMeshPro – ActorUI)アクター残りTPテキスト TPTextの作成
アクターの残りTPを表示するTextMeshProオブジェクト、TPTextを作成します。HPTextからのコピーが簡単です。
- RectTransform:Positionは(97, -11)、サイズは(110, 42)
- TextMeshPro – Text:100<size=60%><color=#222>/100</color></size>
- TextMeshPro – Font Asset:Assets/Fonts/NotoSans_BlackShadow
- TextMeshPro – Material Preset:NotoSans_BlackShadow_HPTP
- TextMeshPro – Font Size:Auto Sizeをオン、サイズは10~26
- TextMeshPro – Vertex Color:濃い目の青色
- TextMeshPro – Spacing Options:Characterを8
- TextMeshPro – Alignment:右揃え

ActorUIオブジェクトをPrefab化・複製
ここまでを一通り設定できたら親オブジェクトであるActorUIをPrefab化していきます。
HierarchビューのActorUIをそのままProjectビューのPrefabフォルダ内にドラッグ&ドロップします。(フォルダを細分化したい方はPrefabフォルダの中にさらにBattleフォルダを作成してください。)

そしてアクターは前衛と後衛でそれぞれ最大3名ずつ表示されるので、ActorUIArea_Vanguardオブジェクト以下にActorUIを3つ、ActorUIArea_Rearguard以下にも3つ置かれるようにコピー&ペーストします。

これで計6つのActorUIをシーン内に用意できましたが、位置を調整していないのでそれぞれ重なって表示されてしまっています。
1つずつ座標を手入力で調整しても良いのですが、後からレイアウトを再調整する場合にはやや手間が発生します。
今回はUIのLayout Group機能を使用してUIオブジェクトを自動整列させてみましょう。
まずはActorUIArea_VanguardオブジェクトのInspectorを開き、下部の[Add Component]ボタンから追加するコンポーネントを選びます。今回はHorizontal Layout Groupを選びます。(検索欄に名称を入力して探すのが早いです。)

このコンポーネントは横方向にUIオブジェクトを並べるのに適しています。アタッチした段階で既にUIの位置に変更が加わっていることを確認できるはずです。
初期設定では中央揃えになっていないため設定を変えていきます。
まず確認するのはChild Alignmentです。ここをMiddle Centerに変更することで中央揃えになります。
Child Force Expandをオフにすると、その方向で各UI同士が密着するように並ぶようになります。
Spacingを調整して各UI同士の距離を数値で指定できます。今回は5にしました。

ActorUIArea_Rearguardオブジェクト側にも同じ設定のコンポーネントを追加することで、画面に6つのActorUIがそれぞれ見えるようになりました。

次はバトルコマンド選択肢用のボタンを作成します。
(Button)バトルコマンドUI BattleCommandUIの作成
このオブジェクトはBattleCommandUIArea以下に作成します。
「通常攻撃」や「スキル発動」などの戦闘時のコマンド入力を行えるButtonオブジェクト、BattleCommandUIを作成します。Hierarchyメニュー内での名称は[Button – TextMeshPro]です。
Buttonとして作成されたオブジェクトは、Imageコンポーネントの他にButtonコンポーネントも併せ持ちます。Buttonコンポーネント側においてマウスクリック(スマートフォンの場合はタップ)の検出、およびクリックされた場合に呼び出す処理(OnClick)を指定できます。
- RectTransform:Positionは(0, 0)、サイズは(180, 58)
- Image – Source Image:Assets/Textures/GUIs/CommandButton.png
- Image – Color:やや薄めの白
Buttonコンポーネントの設定は後から行います。

BattleCommandUI以下のText (TMP)オブジェクト
Buttonオブジェクト作成時には、同時に子オブジェクトとして[Text (TMP)]というオブジェクトが生成されています。こちらは通常のTextMeshProと同様にボタンの文字を表示するためのものです。設定を少し変更します。
オブジェクト名も分かりやすいものに変えてもOKです。
- TextMeshPro – Font Asset:Assets/Fonts/MPLUS1p-Regular SDF
- TextMeshPro – Font Size:26
- TextMeshPro – Vertex Color:白色
- TextMeshPro – Alignment:中央揃え

BattleCommandUIオブジェクトをPrefab化・複製
BattleCommandUIオブジェクトも複数並べて表示するオブジェクトなのでまずはPrefab化を行います。そしてBattleCommandUIAreaオブジェクト以下に合計5つになるように複製を行います。

そしてこれらにもLayout Group機能による自動整列を適用していきます。今回は縦方向に並べたいのでVertical Layout GroupコンポーネントをBattleCommandUIAreaにアタッチします。
- Vertical Layout Group – Spacing:6
- Vertical Layout Group – Child Force Expand:両方オフ

ここに表示しているコマンドは常に表示する文章が同じ(=スクリプトで変更しない)ので、1つ1つにテキストを手入力していきます。
それぞれのText (TMP)オブジェクトおよびTextMeshProコンポーネントを確認し、上から順番に以下のテキストを入力します
- ATTACK
- SKILL
- ITEM
- GUARD
- RUN

EnemyUIオブジェクトの作成とPrefab化
敵グラフィックを表示するための画像オブジェクト、EnemyUIもあわせて作成しておきます。
これはEnemyUIAreaオブジェクト以下に生成・表示されます。画像ファイルはスクリプトから割り当てられるので現在は設定不要ですが、表示の確認に適当な画像を使用してもOKです。
- RectTransform:Positionは(0, 0)、サイズは(178, 188)

EnemyUIオブジェクトの作成が出来たらPrefab化し、シーン上からは一旦削除します。(敵の出現する数にあわせてスクリプトからオブジェクトを生成するため)
また、EnemyUIについては複数の敵が居る場合は横に並べて表示したいのでEnemyUIAreaオブジェクトにHorizontal Layout Groupをアタッチしておきます。
- Horizontal Layout Group – Child Alignment:Middle Center

戦闘シーン用のスクリプトを仮作成
のちほどUIオブジェクトの追加はありますが、ひとまずは動作確認を優先し、スクリプトからのUI表示などが正常に行えるかどうかを見ていきます。
各種アクターUIのHPとTPにランダムな数値を表示させられるかを試しましょう。まずは戦闘シーンの管理を行うクラス、BattleManager.csを作成します。
Scripts/にBattleフォルダを新しく作成して戦闘に関するスクリプトをまとめておくと良いでしょう。
BattleManager.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 |
using System.Collections.Generic; using UnityEngine; /// <summary> /// (Battle) /// バトルマネージャー /// </summary> public class BattleManager : MonoBehaviour { // オブジェクト・コンポーネント参照 // アクターUI [SerializeField] private List<ActorUI> actorUI_Vanguard = null; // 前衛アクターUI参照 [SerializeField] private List<ActorUI> actorUI_Rearguard = null; // 後衛アクターUI参照 private List<ActorUI> actorUIs; // 前衛・後衛を足したアクターUIリスト // Start void Start () { // アクターUI初期化 // 前衛リストと後衛リストをまとめたリストを作成 actorUIs = new List<ActorUI> (actorUI_Vanguard); actorUIs.AddRange (actorUI_Rearguard); // リストを加算 // 全アクターUI初期化 foreach (var actorUI in actorUIs) { // 初期化処理呼び出し actorUI.Init (this); } // デバッグ用に後衛の3人目は非表示 actorUI_Rearguard[2].DisableActorUI (); } } |
- [SerializeField]属性は、privateで宣言した変数(フィールド)をInspectorに表示し、Inspectorから値を設定できるようにする属性です。これによりprivate変数でありながら、Unityエディタ上ではpublic変数と同じように設定することが可能です。
1つ1つのActorUIへの処理は、このあと作成するActorUIクラスにて行います。
BattleManagerクラスではこれらActorUIへの参照を前衛と後衛で分けて取得し、スクリプト内では1つのリストにまとめ、1回ずつ初期化しています。
ActorUI.cs (新規)
まとめ

今回は戦闘画面の各種UIオブジェクトを作成し、それらを組み合わせることで前衛・後衛が存在するウィザードリィや世界樹風のオリジナル多人数戦闘画面を作り上げました。さらにそれらの数値をスクリプトで操作できることを確認しました。
次回は主にスクリプト面を拡張し、実際に操作して戦闘システムを体験できるまでを目標に開発を進めます。
次の記事:

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






コメント