
前回、4人目のメドゥーサが仲間に入って、ロビーでバトルに出る3人を選べるようになりました。でも「地下へ」を押すと、毎回同じ敵と1回戦って、ロビーに戻ってくるだけでした・・・。今回は、地下を「階」に分けて、1つの階で何回か戦いながら奥へ進み、クリアしたら次の階へ行けるようにしたいと思います!
- シリーズの目次:ターン制RPGの作り方
- 前回:#20 なかまの入れ替え
今回作るもの

- 地下は3つの階。1つの階で3回戦うと、その階はクリア
- 階ごとに、出てくる敵の組み合わせと背景がちがう
- 勝つと「さきへ すすむ」か「ロビーへ」を選べる
- 進むと、HPやMPはそのままで次のバトル。3人が右へ走っていく
- ロビーへ帰ると、休憩室や売店が使える(その階は、次に来たとき1回目から)
- 右上に、今いる階と何回目のバトルか(ちか1かい 2/3)を出す
- クリアした階の次の階へ、ロビーの「地下へ」から行けるようになる
- 地下2階へ行けるようになると、売店に めざましどけい・ぶんちん・司書のエプロン が並ぶ
| スクリプト | 役割 | 付ける場所 |
|---|---|---|
| FloorData | 階のデータ(名前・背景・戦う順番の敵の組み合わせ) | (付けない。データのアセット) |
| GameSession | 階のデータと、どこまで進んだか | - |
| BattleLineup | 今いる階の敵と背景で並べる | - |
| ResultWindow | 「さきへ すすむ」のボタン | - |
| UnitView | 右へ走って、画面の外へ | - |
| BattleManager | 右上の階の表示、進む・帰る、階のクリア | - |
| LobbyMenu | 「地下へ」で階を選ぶ | - |
| IShopGoods ほか | 売り物が並ぶようになる階 | - |
階のデータを作ろう

この節では、地下2・3階の敵を足して、階ごとのデータ(FloorData)を作ります。
地下2・3階の敵と背景
素材のTurnBasedRpgAssets.zipに、新しい敵5体と、地下2・3階の背景を足しました。
- zipをダウンロードし直して、
TurnBasedRpg/SpritesのEnemiesとBackgroundsをプロジェクトに入れる- 敵:enemy_quill_pen・enemy_thick_dictionary・enemy_popup_globe・enemy_lamp_ghost・enemy_magic_page
- 背景:bg_library_b2(緑がかった古い書庫)・bg_library_b3(紫の暗い書庫)
- zipの中のunitypackageから入れると、Spriteの設定も入った状態で取り込まれます

- Data/Enemiesに、Create>TurnBasedRpg>Enemy Data で5つ作り、下の表のとおりに入れる
- Commandsは、どれも Attack の1つだけ
| ファイル名 | Enemy Name | Sprite | HP | こうげき | ぼうぎょ | すばやさ | Exp | Gold |
|---|---|---|---|---|---|---|---|---|
| QuillPen | 羽ペン | enemy_quill_pen | 26 | 15 | 6 | 14 | 8 | 8 |
| ThickDictionary | ぶあつい辞書 | enemy_thick_dictionary | 48 | 16 | 16 | 4 | 10 | 12 |
| PopupGlobe | とびだす地球儀 | enemy_popup_globe | 34 | 14 | 10 | 9 | 11 | 10 |
| LampGhost | ランプのおばけ | enemy_lamp_ghost | 40 | 18 | 10 | 12 | 16 | 15 |
| MagicPage | まほうのページ | enemy_magic_page | 30 | 14 | 8 | 13 | 14 | 14 |
- 深い階ほど、能力も、倒したときの経験値・お金も大きくしています。地下1階の敵(HP 12〜22)より、だいぶ強めです
スライム「れんぞくひっかき」「のしかかり」みたいな、この敵たちだけの行動は、次の回で作ります。今回はみんな「たたく」だけ・・・
FloorData


1つの階のデータを、ScriptableObjectで作ります。敵のデータ(#2のEnemyData)と同じように、Inspectorで中身を入れられる「アセット」にします。
- 「FloorData」スクリプトを作る
using UnityEngine;
// 1回のバトルに出てくる敵の組み合わせ
[System.Serializable]
public class EnemyGroup
{
public EnemyData[] enemies; // 出てくる敵(1〜4体)
}
// 地下の1つの階のデータ:名前・背景と、戦う順番に並べた敵の組み合わせ
[CreateAssetMenu(fileName = "NewFloor", menuName = "TurnBasedRpg/Floor Data")]
public class FloorData : ScriptableObject
{
[SerializeField] private string floorName; // 画面に出す名前(ちか1かい)
[SerializeField] private Sprite background; // バトルの背景
[SerializeField] private EnemyGroup[] battles; // 戦う順番に、出てくる敵の組み合わせ(この数だけ戦う)
public string FloorName => floorName;
public Sprite Background => background;
public int BattleCount => battles.Length;
// battleIndex 番目(0 から)のバトルに出てくる敵
public EnemyData[] GetEnemies(int battleIndex)
{
return battles[battleIndex].enemies;
}
}
- EnemyGroup:1回のバトルの「敵の組み合わせ」です。Unityは、配列の配列(
EnemyData[][])をInspectorに出せないので、配列を1つ持つクラスで包んでから、その配列(EnemyGroup[])にしています [System.Serializable]を付けると、MonoBehaviourでもScriptableObjectでもない普通のクラスも、Inspectorで中身を入れられるようになります(#16のItemStackと同じです)- battles:並べた順番に戦います。要素の数が、その階で戦う回数になります
「何回戦うか」を別の数で持たずに、battlesの数で決めています。こうしておくと、数と中身がずれることがありません。あとでボスを足すときも、要素を1つ増やすだけで済みます。
- TurnBasedRpg/Dataに「Floors」フォルダを作り、Create>TurnBasedRpg>Floor Data で3つ作る(Floor1・Floor2・Floor3)
- 上の「地下1〜3階と、戦う順番の敵」の図のとおりに入れる
| ファイル名 | Floor Name | Background | 1回目 | 2回目 | 3回目 |
|---|---|---|---|---|---|
| Floor1 | ちか1かい | bg_library_b1 | SpilledInk・SpilledInk | PaperPlane・PaperPlane・PaperPlane | Bookworm・SpilledInk |
| Floor2 | ちか2かい | bg_library_b2 | QuillPen・QuillPen | ThickDictionary・QuillPen | PopupGlobe・PopupGlobe |
| Floor3 | ちか3かい | bg_library_b3 | LampGhost・LampGhost | MagicPage・MagicPage・MagicPage | LampGhost・MagicPage・MagicPage |
GameSession


階のデータと「どこまで進んだか」は、シーンをまたいで覚えておきたいので、#17で作ったGameSessionに持たせます。
startGoldの下に、欄を足します。
[SerializeField] private FloorData[] floors; // 地下の階(上から 地下1・地下2・地下3)
Goldの下に、プロパティを足します。
public FloorData[] Floors => floors;
public int ClearedFloorCount { get; set; } // クリアした階の数(地下1階をクリアしたら 1)
public int ReachedFloorCount => Mathf.Min(ClearedFloorCount + 1, floors.Length); // 行ける階の数(クリアした階の、1つ下まで)
public int FloorIndex { get; set; } // 今いる階(0 が地下1階)
public int BattleIndex { get; set; } // その階の、何回目のバトルか(0 から)
public FloorData CurrentFloor => floors[FloorIndex];
- ClearedFloorCount:クリアした階の数です。覚えておくのはこの数だけで、行ける階の数(
ReachedFloorCount)は、ここから計算します - ReachedFloorCount:クリアした階の1つ下まで行けます。地下3階より下は無いので、
Mathf.Minで階の数より大きくならないようにしています - FloorIndex・BattleIndex:今いる階と、その階の何回目か。ロビーで階を選んだときに決めて、勝つたびに
BattleIndexを1つ進めます - Hierarchyの GameSession を選び、Floorsを 3 にして、Floor1・Floor2・Floor3 を順に入れる
地下を進もう


この節では、Battleシーンを「今いる階の、何回目のバトル」にして、勝ったら先へ進めるようにします。
次のバトルのために新しいシーンは作りません。同じBattleシーンを、もう一度読み込みます。読み込み直すたびに、GameSessionのBattleIndexを見て、出てくる敵を変えます。
今いる階の敵と背景で並べる
#17で、仲間と持ち物はGameSessionから読むようにしました。敵も同じように、GameSessionの今いる階から読みます。
BattleLineupの一番上にusing UnityEngine.UI;を足して(Imageを使うので)、enemiesの欄を次のように書き換えます。
[SerializeField] private EnemyData[] enemies; // 確認用:Battle シーンから再生したときの敵(1〜4体)
[SerializeField] private Image background; // バトルの背景(階ごとに変える)
Setupの、敵を並べるループを次のように書き換えます。
EnemyData[] enemyGroup = LoadEnemies();
for (int i = 0; i < enemyGroup.Length; i++)
{
EnemyData enemy = enemyGroup[i];
UnitView view = Instantiate(enemyPrefab, enemyArea);
// 真ん中をそろえて横に並べ、1体おきに上下へずらす
float x = (i - (enemyGroup.Length - 1) / 2f) * enemySpacing;
float y = (i % 2 == 0) ? 60f : -60f;
((RectTransform)view.transform).anchoredPosition = new Vector2(x, y);
view.SetupEnemy(enemy);
EnemyUnits.Add(new BattleUnit(enemy, view));
}
LoadPartyの上に、次のメソッドを足します。
// ロビーから来たら、今いる階の背景にして、その階の何回目かのバトルの敵を出す
// Battle シーンから再生したとき(GameSession が無い)は、確認用に Inspector の敵を出す
private EnemyData[] LoadEnemies()
{
GameSession session = GameSession.Instance;
if (session == null)
{
return enemies;
}
FloorData floor = session.CurrentFloor;
background.sprite = floor.Background;
return floor.GetEnemies(session.BattleIndex);
}
enemiesは、partyやstartItemsと同じ「Battleシーンから再生したときの確認用」になります- Hierarchyの Battle を選び、Battle LineupのBackgroundに、Canvasの Background を入れる
今いる階のウインド


今どの階の、何回目のバトルなのかが分かるように、右上に小さなウインドを出します。ロビーのお金のウインド(GoldWindow)と同じ形なので、コピーして使います。


- Lobbyシーンを開き、HierarchyのGoldWindowを選んでCtrl+C
- Battleシーンを開き、Canvasを右クリック>Paste As Child
- 名前を「FloorWindow」にして、MessageWindowのすぐ下に置く
- Gold Counterのコンポーネントを外す(右上の︙>Remove Component)
- Widthを 420 にする(「ちか1かい 1/3」が1行に収まるように)
- 子のGoldTextの名前を「FloorText」にする
Widthがお金のウインドと同じ280のままだと、「ちか1かい」と「1/3」が2行に折り返して、枠からはみ出してしまいます。階の名前を長くしたときも、1行に収まるようにWidthを広げてください。
BattleManagerのsceneFaderの下に、欄を足します。
[SerializeField] private GameObject floorWindow; // 右上の、今いる階のウインド
[SerializeField] private TMP_Text floorText; // 今いる階と、何回目のバトルか(ちか1かい 2/3)
StartBattleAsyncで、lineup.Setup();の下に1行足します。
ShowFloor();
SelectActionsAsyncの上に、次のメソッドを足します。
// 右上に、今いる階と、何回目のバトルか(Battle シーンから再生したときは、ウインドを隠す)
private void ShowFloor()
{
GameSession session = GameSession.Instance;
floorWindow.SetActive(session != null);
if (session != null)
{
FloorData floor = session.CurrentFloor;
floorText.text = $"{floor.FloorName} {session.BattleIndex + 1}/{floor.BattleCount}";
}
}
BattleIndexは0から数えているので、画面には+ 1して「1/3」から出します- Battleオブジェクトの Battle Manager に、Floor Window(FloorWindow)・Floor Text(FloorText)を入れる
結果のウインドに「さきへ すすむ」


勝ったときのウインド(#11のResultWindow)に、「さきへ すすむ」のボタンを足します。負けたときや、その階の最後のバトルでは、このボタンは出しません。


- Hierarchyで ResultWindow を右クリック>Create Empty で空のオブジェクトを作り、名前を「Buttons」にする
- Rect Transform:アンカーを下の真ん中(bottom-center)、Pos Y 80、Width 640、Height 64
- Add Component>Horizontal Layout Group:Spacing 40、Child Alignment:Middle Center、Control Child SizeとChild Force Expandのチェックは全部外す
- RetryButton(ロビーへ)を、Buttonsの中へドラッグする
- RetryButtonを選んでCtrl+Dで複製し、名前を「NextButton」にして、Buttonsの一番上(RetryButtonの上)に置く
- 子のText (TMP)の文字を「さきへ すすむ」にする
- 一番上のチェックを外して、隠しておく
9-6 Scroll ViewとLayout Groupでリストを作ろうのHorizontal Layout Groupは、隠した子を飛ばして並べます。なので、NextButtonを隠すと、ロビーへのボタンだけが真ん中に来ます。位置を自分で計算しなくていいので楽ですね。
ResultWindowを、次のように書き換えます。
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
// バトルが終わったときのウインド(勝った・負けた・にげた)。「ロビーへ」か「さきへ すすむ」が押されるまで待つ
public class ResultWindow : MonoBehaviour
{
[SerializeField] private TMP_Text titleText;
[SerializeField] private TMP_Text bodyText;
[SerializeField] private Button retryButton; // ロビーへ
[SerializeField] private Button nextButton; // さきへ すすむ(まだ先のバトルがあるときだけ出す)
// どちらかのボタンが押されたら、待っているところに知らせる(さきへ すすむ なら true)
private readonly AwaitableCompletionSource<bool> choiceSource = new AwaitableCompletionSource<bool>();
private void Awake()
{
retryButton.onClick.AddListener(() => choiceSource.TrySetResult(false));
nextButton.onClick.AddListener(() => choiceSource.TrySetResult(true));
gameObject.SetActive(false); // 最初は隠しておく
}
// ウインドを出して、ボタンが押されるまで待つ。canGoOn が true なら「さきへ すすむ」も出す
// 「さきへ すすむ」が押されたら true
public async Awaitable<bool> ShowAsync(string title, string body, bool canGoOn = false)
{
titleText.text = title;
bodyText.text = body;
nextButton.gameObject.SetActive(canGoOn);
choiceSource.Reset();
gameObject.SetActive(true);
// 最後のメッセージを読んだときの決定が、このフレームに残っていることがあるので、1フレーム待ってから選ぶ
await Awaitable.NextFrameAsync(destroyCancellationToken);
Button firstButton = canGoOn ? nextButton : retryButton; // 先へ進めるなら、そちらを先に選んでおく
EventSystem.current.SetSelectedGameObject(firstButton.gameObject);
bool goesOn = await choiceSource.Awaitable;
gameObject.SetActive(false);
return goesOn;
}
}
- AwaitableCompletionSource<bool>:今までは「押された」ことだけを知らせていましたが、どちらのボタンが押されたかを
boolで返すようにしました。#6で、選んだ相手を返したAwaitableCompletionSource<UnitView>と同じ形です - ボタンが押されたときの処理は1行だけなので、メソッドを作らずにラムダ式(
() => …)で登録しています canGoOn = falseのように、引数に= 値を書いておくと、呼ぶときに省略できます。負けた・にげたときのShowAsync("ぜんめつ…", …)は、今までのままでOKです- ResultWindowの Result Window に、Next Button(NextButton)を入れる
ResultWindowは「どちらが押されたか」を返すだけで、押されたあとに何をするか(次のバトルへ・ロビーへ)は、呼んだBattleManagerが決めます。ウインドは選ばせることだけに集中させておくと、あとでボタンを増やすときも直す場所が少なくて済みます。
走って次のバトルへ
「さきへ すすむ」を選んだら、3人が右へ走って画面の外へ出ていき、それから次のバトルにします。#11の、にげるときのRunAwayAsyncの反対向きです。
UnitViewのRunAwayAsyncの下に、次のメソッドを足します。
// 先へ進む:右を向いたまま、画面の外へ走っていく
public async Awaitable RunForwardAsync()
{
Vector2 from = rectTransform.anchoredPosition;
Vector2 to = from + new Vector2(1800f, 0f);
const float seconds = 0.7f;
float time = 0f;
while (time < seconds)
{
time += Time.deltaTime;
rectTransform.anchoredPosition = Vector2.Lerp(from, to, time / seconds);
await Awaitable.NextFrameAsync(destroyCancellationToken);
}
}
- 仲間は画面の左にいるので、1800右へ動かすと、画面(横1920)の右の外まで出ます
BattleManagerのRunAsyncを直していきます。まず、phase = BattlePhase.Start;の下に変数を足します。
bool goesOn = false; // 勝って「さきへ すすむ」を選んだら true
BattlePhase.Victoryのところで、ShowVictoryAsyncの結果を受け取ります。
case BattlePhase.Victory:
goesOn = await ShowVictoryAsync();
RunAsyncの最後の、ロビーに戻るところを次のように書き換えます。
if (goesOn)
{
// 「さきへ すすむ」:みんなで右へ走っていって、同じシーンで次のバトル
await RunForwardAsync();
await sceneFader.LoadSceneAsync("Battle");
}
else
{
// 「ロビーへ」が押された:暗くして、ロビーに戻る
await sceneFader.LoadSceneAsync("Lobby");
}
- 先へ進むときも、その上の「バトルの結果を持ち越す」(
SaveToMember)は通ります。なので、減ったHPやMPは、そのまま次のバトルに持ち越されます
ShowVictoryAsyncを、boolを返すように書き換えます(コメントを1行足して、AwaitableをAwaitable<bool>にします)。
// 「さきへ すすむ」を選んだら true
private async Awaitable<bool> ShowVictoryAsync()
ShowVictoryAsyncの最後のresultWindow.ShowAsync(…)の行を、次のように書き換えます。
return await ShowVictoryResultAsync($"けいけんち {exp}ポイント\n{gold}ゴールドを てにいれた");
ShowVictoryAsyncの下に、2つのメソッドを足します。
// 勝ったときのウインド。その階にまだバトルが残っていれば「さきへ すすむ」も出す(選んだら true)
// 最後のバトルなら、その階をクリアして、次の階へ行けるようにする
private async Awaitable<bool> ShowVictoryResultAsync(string body)
{
GameSession session = GameSession.Instance;
if (session == null)
{
await resultWindow.ShowAsync("しょうり!", body); // Battle シーンから再生したときは、ロビーへ戻るだけ
return false;
}
FloorData floor = session.CurrentFloor;
session.BattleIndex++;
if (session.BattleIndex < floor.BattleCount)
{
return await resultWindow.ShowAsync("しょうり!", body, true);
}
// その階の最後のバトルに勝った:クリア。はじめてなら、次の階へ行けるようになる
await messageWindow.ShowAsync($"{floor.FloorName}を クリアした!");
if (session.FloorIndex == session.ClearedFloorCount)
{
session.ClearedFloorCount++;
int nextIndex = session.FloorIndex + 1;
if (nextIndex < session.Floors.Length)
{
await messageWindow.ShowAsync($"{session.Floors[nextIndex].FloorName}へ いけるように なった!");
}
}
await resultWindow.ShowAsync("クリア!", body);
return false;
}
// 先へ進む:立っている仲間が、少しずつずれて右へ走っていく
private async Awaitable RunForwardAsync()
{
List<Awaitable> runs = new List<Awaitable>();
foreach (BattleUnit unit in lineup.PartyUnits)
{
if (unit.IsDead)
{
continue; // 倒れている人は、その場で眠ったまま(次のバトルにも、倒れたまま出る)
}
unit.View.ResumeIdle(); // 喜ぶポーズから、走る(弾む)すがたに戻す
runs.Add(unit.View.RunForwardAsync());
await Awaitable.WaitForSecondsAsync(0.08f, destroyCancellationToken);
}
foreach (Awaitable run in runs)
{
await run;
}
}
- BattleIndex++:勝ったら、次のバトルの番号へ進めます。まだその階のバトルが残っていれば、「さきへ すすむ」も出します
- 最後のバトルなら、その階はクリアです。クリアのところは、次の節で説明します
- RunForwardAsync:3人いっしょに走り出すより、0.08秒ずつずらすと、ばらばらに駆け出していく感じになります。始めるのだけずらして、着くのはあとでまとめて待ちます(#20の「先に始めてから、順に
await」と同じです)
次の階へ


この節では、クリアした階を覚えて、ロビーから次の階へ行けるようにします。
クリアした階を覚える
前の節のShowVictoryResultAsyncの後半が、階のクリアです。
- その階の最後のバトルに勝ったら「〇〇を クリアした!」
session.FloorIndex == session.ClearedFloorCountは、「今いる階が、まだクリアしていない一番上の階か」です。地下1階(0)を初めてクリアしたとき、ClearedFloorCountは0なので、ここに入って1になります- もう一度地下1階をクリアしても、
ClearedFloorCountはもう1なので、増えません(行ける階が勝手に増えないように) - 次の階があれば「〇〇へ いけるように なった!」と知らせます。地下3階には次の階が無いので、出しません
ロビーで階を選ぶ


ロビーの「地下へ」を押したら、行く階の一覧を出します。まだ行けない階は灰色にして、「この先にまだ階がある」ことが分かるようにしています。


- Lobbyシーンを開き、ShopWindowを選んでCtrl+Dで複製し、名前を「FloorWindow」にする(隠したまま。PartyWindowの下に移す)
LobbyMenuのdungeonButtonの下に、欄を足します。
[SerializeField] private CommandMenu floorMenu; // 行く階の一覧(FloorWindow)
OnDungeonClickedを次のように書き換えて、その下にChooseFloorAsyncを足します。
// 地下へ:行く階を選んで、その階の1回目のバトルへ(キャンセルしたら、メニューに戻る)
private async void OnDungeonClicked()
{
if (isBusy)
{
return;
}
isBusy = true;
menuGroup.interactable = false;
try
{
int floorIndex = await ChooseFloorAsync();
if (floorIndex >= 0)
{
GameSession session = GameSession.Instance;
session.FloorIndex = floorIndex;
session.BattleIndex = 0;
await sceneFader.LoadSceneAsync("Battle");
return;
}
}
catch (System.OperationCanceledException)
{
return; // シーンが切り替わったら、そこで終わり
}
BackToMenu(dungeonButton);
}
// 地下の階の一覧から、行く階を選ぶ(まだ行けない階は灰色)。キャンセルなら -1
private async Awaitable<int> ChooseFloorAsync()
{
GameSession session = GameSession.Instance;
FloorData[] floors = session.Floors;
string[] names = new string[floors.Length];
string[] values = new string[floors.Length];
bool[] usables = new bool[floors.Length];
for (int i = 0; i < floors.Length; i++)
{
FloorData floor = floors[i];
names[i] = floor.FloorName;
values[i] = i < session.ClearedFloorCount ? "クリア" : "";
usables[i] = i < session.ReachedFloorCount;
}
messageText.text = "どの かいへ いく?";
floorMenu.gameObject.SetActive(true);
// 最初は、行ける中で一番深い階を選んでおく
int floorIndex = await floorMenu.WaitForChoiceAsync(names, values, usables, session.ReachedFloorCount - 1);
floorMenu.gameObject.SetActive(false);
return floorIndex;
}
- 一覧は、#18で作った
WaitForChoiceAsyncです。右はしには、クリアした階に「クリア」を出します - 階を選んだら、
FloorIndexをその階に、BattleIndexを0にしてから、Battleシーンを読み込みます。途中でロビーへ帰った階も、次は1回目からです - 一番深い階を最初に選んでおくと、Enterを押すだけで、新しい階へ進めます
キャンセルしたときに、メニューへ戻る処理は、#19のOpenSubMenuの後半と同じです。なので、そこをメソッドに分けて、両方から使います。OpenSubMenuの、menuGroup.interactable = true;からisBusy = false;までをBackToMenu(button);の1行にして、OpenSubMenuの下に次のメソッドを足します。
// ロビーのメニューに戻る(button を選び直す)
private void BackToMenu(Button button)
{
menuGroup.interactable = true;
messageText.text = "ここは まほう図書館の ロビー。";
ShowParty(); // 装備で最大HPなどが変わったときのために、出し直す
EventSystem.current.SetSelectedGameObject(button.gameObject);
isBusy = false;
}


- Lobbyオブジェクトの Lobby Menu の Floor Menu に、FloorWindow を入れる



灰色の「ちか3かい」が見えていると、早く行ってみたくなるでしょ?
売店の品ぞろえを増やす


#18 売店で作ったきり、まだ並べていなかった強い装備を、深い階へ行けるようになったら並べます。
売り物(IShopGoods)に、「この階まで行けるようになったら並ぶ」という数を足します。IShopGoodsのPriceの下に1行足します。
int ShopFloor { get; } // 売店に並ぶのは、この階まで行けるようになってから(1 なら最初から)
ItemDataとEquipmentDataのpriceの欄の下に、欄を足します(コメントの位置は、それぞれの欄に合わせてください)。
[SerializeField] private int shopFloor = 1; // 売店に並ぶようになる階(2 なら、地下2階へ行けるようになってから)
どちらも、Priceのプロパティの下に1行足します。
public int ShopFloor => shopFloor;
ShopのOpenAsyncで、売り物のListを作ったあとに、まだ並べないものを取りのぞきます。
List<IShopGoods> goodsList = new List<IShopGoods>();
goodsList.AddRange(items);
goodsList.AddRange(equipments);
// まだ行けない階の売り物は、並べない
goodsList.RemoveAll(product => product.ShopFloor > session.ReachedFloorCount);
- RemoveAll:Listから、条件に合うものを全部取りのぞきます。条件はラムダ式で書きます(
productは、Listの1つずつ) - Shopの欄には、売り物を全部入れておくだけで、並ぶかどうかは、それぞれのデータの
shopFloorで決まります


- 次の5つの Shop Floor を変える(ほかは1のまま)
- 2:AlarmClock(めざましどけい)・Paperweight(ぶんちん)・LibrarianApron(司書のエプロン)
- 3:MagicPen(まほうのペン)・MagicCape(まほうのマント)


- Lobbyの Shop を選び、Itemsに AlarmClock、Equipmentsに Paperweight・LibrarianApron・MagicPen・MagicCape を足す
動かして確認!


- Lobbyシーンを開いて再生し、「地下へ」→ ちか1かい
- 右上に「ちか1かい 1/3」。こぼれたインク2体とのバトルになる
- 勝つと「さきへ すすむ」と「ロビーへ」。進むと3人が右へ走っていき、紙ひこうき3体の「2/3」になる
- 3回目に勝つと「ちか1かいを クリアした!」「ちか2かいへ いけるように なった!」で、ロビーへ
- 「地下へ」の一覧で、ちか1かい に「クリア」、ちか2かい が選べる。ちか3かい は灰色
- 売店に、めざましどけい・ぶんちん・司書のエプロンが並ぶ
- ちか2かい は、背景が緑がかった書庫になり、羽ペンなどの強い敵が出る
GIFは、確かめやすいように、仲間を最初からLv4にして撮っています。Lv1のままだと、地下1階の3回でもHPがけっこう減るので、途中で一度ロビーへ帰って休憩室に寄るのもアリです。
#21の動作確認
- ロビーの「地下へ」で、階の一覧が出る(まだ行けない階は灰色)
- 右上に、今いる階と何回目のバトルか(ちか1かい 1/3)が1行で出る
- 勝つと「さきへ すすむ」「ロビーへ」を選べる。最後のバトルでは「ロビーへ」だけ
- 「さきへ すすむ」で、立っている仲間が右へ走っていき、次のバトルになる(HP・MPはそのまま)
- 階の3回目に勝つと、その階をクリアして、次の階へ行けるようになる
- 地下2階へ行けるようになると、売店の品物が増える
あとがき
今回は、地下を3つの階に分けて、何回か戦いながら奥へ進めるようにしました。階の中身をFloorDataにまとめたので、敵の組み合わせを変えたり、戦う回数を増やしたりするのは、Inspectorだけで出来ます。次回は、地下2・3階の敵に、それぞれの特別な行動を付けたいと思います!



地下2階の羽ペン、「たたく」だけなのに、もうけっこう痛いです・・・



ぶんちんと司書のエプロンを買ってから行くといいわよ!
コメント
コメント一覧 (1件)
[…] 前回:#21 地下へ進もう […]