ターン制RPGの作り方#20|なかまの入れ替え:4人の中から、バトルに出る3人を選ぼう

ロビーで「なかま」を選ぶと、右に4人の一覧が開く。メドゥーサの右はしには「ひかえ Lv1」。キョンシーを選んでからメドゥーサを選ぶと、2人がぴょんと跳んで場所を入れ替わり、「キョンシーと メドゥーサが いれかわった!」。左の窓ぎわで本を読んでいるのがキョンシーになり、下のステータスの3行目がメドゥーサに変わる
2人を選んで入れ替える

前回の装備の画面で、買った装備を付け替えて強くなれるようになりました。ところで、仲間の素材は4人分あるのに、ロビーにもバトルにも3人しかいませんでした・・・。今回は4人目のメドゥーサを仲間に入れて、ロビーの「なかま」で、バトルに出る3人を入れ替えられるようにしたいと思います!

目次

今回作るもの

ロビーの画面。左の窓ぎわで、メドゥーサが正面を向いて本を読んでいる。真ん中にフェアリー・スライムちゃん・キョンシー。左下のメニューの「なかま」が、白い(押せる)ボタンになっている
控えのメドゥーサは、ロビーのすみで本を読んで待つ
  • 仲間を4人にする。並び順の上の3人がバトルに出て、4人目は控え
  • 控えの仲間は、ロビーのすみで本を読んで待っている
  • ロビーのメニューの「なかま」で、2人を選ぶと、その2人の並び順を入れ替える
    • 選んでいる人が白く光る。2人目を選んでいる間は、1人目も光ったまま
    • 入れ替えると、2人が相手の場所へぴょんと跳ぶ
    • バトルに出る3人どうしを入れ替えれば、並び順(コマンドを選ぶ順番)も変えられる
  • 控えの仲間も、勝ったときの経験値を半分もらう(置いていかれないように)
スクリプト役割付ける場所
GameSession仲間を4人に。上の3人(Party)と控え(Reserves)に分ける-
PartyMember控えの仲間が、経験値をもらう(付けない)
UnitView本を読んで待つ・相手の場所へ跳ぶ-
PartyMenuなかまの入れ替えの画面Lobby の PartyMenu
LobbyMenu「なかま」のボタン、控えの見た目-
BattleManager控えにも経験値の半分-

仲間を4人にしよう

左に「Members(並び順)」の4つの箱が縦に並ぶ。[0] スライム・[1] フェアリー・[2] キョンシーの3つは緑の「Party(上から3人):バトルに出る・ロビーの3人」へ、[3] メドゥーサは黄色の「Reserves(4人目から):控え」へ線でつながっている
並び順の上の3人がバトルに出る

この節では、GameSessionに4人目を入れて、「バトルに出る3人」と「控え」に分けます。

#17 ロビーと休憩室で作ったGameSessionのPartyには、3人だけが入っていました。これを「4人全員の並び順(Members)」に変えて、Partyは「Membersの上から3人」を返すようにします。こうしておくと、入れ替えはMembersの順番を変えるだけで済みます。

GameSession

GameSessionのInspector。Game Session (Script)のStart Membersが4つになり、Element 0から順にSlime・Fairy・Jiangshi・Medusa (Character Data)。その下にStart Items(HerbTea 3つ)とStart Gold 50
Start Membersに4人

GameSessionのstartPartyとPartyのところを、次のように書き換えます。

    [SerializeField] private CharacterData[] startMembers; // 最初の仲間(4人。上の3人がバトルに出る)
    public const int PartySize = 3; // バトルに出る人数

    public List<PartyMember> Members { get; } = new List<PartyMember>(); // 仲間全員(この並び順の、上の3人がバトルに出る)
    public List<PartyMember> Party => Members.GetRange(0, Mathf.Min(PartySize, Members.Count)); // バトルに出る3人
    public List<PartyMember> Reserves => Members.GetRange(Party.Count, Members.Count - Party.Count); // 控え(4人目から)

Awakeで仲間を作るところも、Membersに入れるように直します。

        foreach (CharacterData data in startMembers)
        {
            Members.Add(new PartyMember(data, 0));
        }
  • Members:4人全員です。この並び順の上の3人がバトルに出ます
  • Party:GetRange(始めの番号, 数)は、Listの一部を取り出した新しいListを返します(Listは6-13 数が変わるデータを扱おう:List)。Mathf.Minは、仲間が3人より少ないときのためです
  • Reserves:上の3人より後ろ、4人目からです
  • Partyは「取り出したList」なので、Party.Addのように書き換えてもMembersには入りません。仲間を増やしたり並びを変えたりするのは、Membersのほうです

バトルの側(#17で作ったBattleLineupのLoadParty)は、今までどおりGameSession.Instance.Partyを使っているので、何も変えなくてOKです。並び順の上の3人が、そのままバトルに出ます。

  • Hierarchyの GameSession を選び、Start Membersを 4 にして、Slime・Fairy・Jiangshi・Medusa を順に入れる(Data>Charactersから)
スライム

名前を変えた欄(startParty → startMembers)は、Inspectorで入れ直しになります・・・

控えは、ロビーのすみで本を読んで待つ

メドゥーサとキョンシーの book_01・book_02・book_03 を3つずつ並べた画像。book_02 だけ背景が緑で「(使う)」。book_02 は2人とも正面を向いて本を開いている
控えの止め絵は book_02

控えの仲間も、ロビーに出しておきます。走ったり弾んだりはせずに、正面を向いて本を読んでいる絵にします。#14で、まほうを覚えたときに使った book のポーズのうち、正面を向いている2枚目(book_02)を止め絵に使います。

UnitViewのPlayFramesAsyncの上に、次のメソッドを足します。

    // 控え:正面を向いて、本を読んで待っている(book の2枚目。正面を向いていて、止め絵に向いている)
    public void ShowReading()
    {
        idleBounce.enabled = false;
        image.sprite = bookFrames[1];
    }
  • 待機の弾み(IdleBounce)を止めてから絵を変えます。止めないと、次のコマで待機の絵に戻ってしまいます
  • 立ち上がるときは、今までのResumeIdleで待機に戻せます
LobbyのHierarchyで、Stage>PartyAreaの中のFairy・Slime・Jiangshiの下にReserveViewが増えている。InspectorはReserveViewで、Rect TransformはPos X -590・Pos Y -10、Width 340・Height 340、Unit Viewが付いている
控えの場所 ReserveView
  • Hierarchyで、Stage>PartyAreaの Slime を選んでCtrl+Dで複製し、名前を「ReserveView」にする
  • Pos X -590、Pos Y -10(左の窓ぎわ)
フェアリー

右の本棚の前は、一覧のウインドが開くと隠れちゃうから、左の窓ぎわにしたのよ!

なかまを入れ替える画面を作ろう

「キョンシーと だれを いれかえる?」。光っているキョンシーはそのままで、一覧で↓を押すと、窓ぎわのメドゥーサも光る。決めると2人が跳んで入れ替わる
1人目は光ったまま、2人目を選ぶ

この節では、ロビーに「なかま」の画面を作ります。

ボタンと一覧

LobbyのHierarchyで、LobbyWindowの中のPartyButtonを選んでいる。InspectorのButtonのInteractableにチェックが入っている
なかま のボタンを押せるように
  • LobbyWindowの中の PartyButton(なかま)を選んで、Buttonの Interactable にチェックを入れる
    • #17で、まだ押せないようにしておいたボタンです
Canvasの中のPartyWindowのInspector。一番上のチェックが外れていて、Rect TransformはPos X 1450、Pos Y 560、Width 560、Height 448。HierarchyではCompareWindowの下にPartyWindow
ShopWindowを複製したPartyWindow
  • ShopWindowを選んでCtrl+Dで複製し、名前を「PartyWindow」にする(隠したまま。CompareWindowの下に移す)

#18 売店・#19 装備の画面と同じ一覧なので、左に名前、右はしにレベルが出せます。控えの人は、右はしに「ひかえ」も出します。

跳んで入れ替わる

2人が入れ替わるところのアップ。キョンシーは左を向いて窓ぎわへ、メドゥーサは右を向いて真ん中へ、山なりに跳んでいく。着いたら、窓ぎわのキョンシーは本を読み、メドゥーサは待機で弾む
相手の場所へ、ぴょんと跳ぶ

入れ替えたときに、ただ絵が変わるだけだと、何が起きたか分かりにくいですよね。2人が相手の場所へ山なりに跳ぶ演出を付けます。

UnitViewのUnitの下に、もとの位置を読めるプロパティを足します。

    public Vector2 HomePosition => homePosition; // もとの位置(なかまの入れ替えで、相手の場所へ跳ぶのに使う)

ShowReadingの下に、跳ぶメソッドと、もとに戻すメソッドを足します。

    // なかまの入れ替え:target の場所へ、山なりに ぴょんと跳ぶ
    public async Awaitable HopToAsync(Vector2 target)
    {
        const float seconds = 0.45f;
        const float height = 120f; // 跳ぶ高さ
        Vector2 from = rectTransform.anchoredPosition;
        if (target.x < from.x)
        {
            transform.localScale = new Vector3(-1f, 1f, 1f); // 左へ跳ぶときは、左を向く
        }
        float time = 0f;
        while (time < seconds)
        {
            time += Time.deltaTime;
            float t = Mathf.Clamp01(time / seconds);
            // 横はまっすぐ、高さは Sin で 0 → 1 → 0
            rectTransform.anchoredPosition = Vector2.Lerp(from, target, t) + new Vector2(0f, Mathf.Sin(t * Mathf.PI) * height);
            await Awaitable.NextFrameAsync(destroyCancellationToken);
        }
        rectTransform.anchoredPosition = target;
    }

    // もとの位置・向きに戻す(なかまの入れ替えで、跳んだあと)
    public void ReturnHome()
    {
        rectTransform.anchoredPosition = homePosition;
        transform.localScale = Vector3.one;
    }
  • HopToAsync:横はLerpでまっすぐ進み、高さにSinを足します。tが0→1のとき、Sin(t × π)は0→1→0なので、山なりになります
  • 仲間の絵は右を向いているので、左へ跳ぶときはlocalScaleのXを-1にして左を向かせます(#11の、にげるときと同じやり方です)
  • ReturnHome:跳んだあと、場所と向きをもとに戻します。このあとで絵を入れ替えるので、見た目は「相手の場所に着いた」ままです

PartyMenu

LobbyのPartyMenuオブジェクトのInspector。Party Menu (Script)のList MenuにPartyWindow、Message WindowにMessageWindow、Message TextにMessageText、Member ViewsにSlime・Fairy・Jiangshi・ReserveView、Lobby MenuにLobby
PartyMenuのInspector

なかまの画面のスクリプトを作ります。

  • 「PartyMenu」スクリプトを作る
using TMPro;
using UnityEngine;

// なかまの入れ替え:2人を選ぶと、その2人の並び順を入れ替える(上の3人がバトルに出る)
public class PartyMenu : MonoBehaviour
{
    [SerializeField] private CommandMenu listMenu;     // 一覧(PartyWindow)
    [SerializeField] private MessageWindow messageWindow;
    [SerializeField] private TMP_Text messageText;     // 上のメッセージ(「だれを いれかえる?」をすぐ出す)
    [SerializeField] private UnitView[] memberViews;   // 並び順の場所(PartyArea の3人と、控えの ReserveView)
    [SerializeField] private LobbyMenu lobbyMenu;      // 入れ替えたら、ロビーの仲間とステータスを出し直す

    // なかまの画面を開いて、キャンセルされるまで入れ替えをする
    public async Awaitable OpenAsync()
    {
        GameSession session = GameSession.Instance;
        listMenu.gameObject.SetActive(true);
        int firstIndex = 0;
        while (true)
        {
            // 一覧:名前と、右はしにレベル(入れ替えると変わるので、毎回作り直す)
            string[] names = MemberNames(session);
            string[] values = MemberValues(session);
            bool[] usables = Usables(session);

            // 1人目:選んでいる人を光らせる
            messageText.text = "だれを いれかえる?";
            listMenu.OnSelect = index => Highlight(index, -1);
            firstIndex = await listMenu.WaitForChoiceAsync(names, values, usables, firstIndex);
            if (firstIndex < 0)
            {
                break; // キャンセル:なかまの画面を閉じる
            }

            // 2人目:1人目は光らせたまま、選んでいる人も光らせる
            int chosenIndex = firstIndex; // ラムダ式の中で使うので、別の変数にしておく
            messageText.text = $"{session.Members[firstIndex].Data.CharacterName}と だれを いれかえる?";
            listMenu.OnSelect = index => Highlight(chosenIndex, index);
            int secondIndex = await listMenu.WaitForChoiceAsync(names, values, usables, firstIndex);
            listMenu.OnSelect = null;
            Highlight(-1, -1);
            if (secondIndex < 0 || secondIndex == firstIndex)
            {
                continue; // キャンセル・同じ人:1人目を選び直す
            }
            await SwapAsync(firstIndex, secondIndex);
        }
        listMenu.OnSelect = null;
        Highlight(-1, -1);
        listMenu.gameObject.SetActive(false);
    }

    // 2人が相手の場所へ跳んで、並び順を入れ替える
    private async Awaitable SwapAsync(int indexA, int indexB)
    {
        GameSession session = GameSession.Instance;
        PartyMember memberA = session.Members[indexA];
        PartyMember memberB = session.Members[indexB];
        UnitView viewA = memberViews[indexA];
        UnitView viewB = memberViews[indexB];

        // 本を読んでいた控えも、立ち上がって跳ぶ。2人いっしょに跳ばしてから、両方を待つ
        viewA.ResumeIdle();
        viewB.ResumeIdle();
        Awaitable hopA = viewA.HopToAsync(viewB.HomePosition);
        Awaitable hopB = viewB.HopToAsync(viewA.HomePosition);
        await hopA;
        await hopB;

        // 並び順を入れ替える。見た目は、場所をもとに戻して、絵を入れ替える(同じように見える)
        session.Members[indexA] = memberB;
        session.Members[indexB] = memberA;
        viewA.ReturnHome();
        viewB.ReturnHome();
        lobbyMenu.ShowParty();
        await messageWindow.ShowAsync($"{memberA.Data.CharacterName}と {memberB.Data.CharacterName}が いれかわった!");
    }

    // 一覧の左:名前
    private string[] MemberNames(GameSession session)
    {
        string[] names = new string[session.Members.Count];
        for (int i = 0; i < session.Members.Count; i++)
        {
            names[i] = session.Members[i].Data.CharacterName;
        }
        return names;
    }

    // 一覧の右はし:レベル(控えには「ひかえ」も)
    private string[] MemberValues(GameSession session)
    {
        string[] values = new string[session.Members.Count];
        for (int i = 0; i < session.Members.Count; i++)
        {
            string level = $"Lv{session.Members[i].Level}";
            values[i] = i < GameSession.PartySize ? level : $"ひかえ  {level}";
        }
        return values;
    }

    // だれでも選べる
    private bool[] Usables(GameSession session)
    {
        bool[] usables = new bool[session.Members.Count];
        for (int i = 0; i < usables.Length; i++)
        {
            usables[i] = true;
        }
        return usables;
    }

    // indexA と indexB の人だけ光らせる(-1 なら、光らせない)
    private void Highlight(int indexA, int indexB)
    {
        for (int i = 0; i < memberViews.Length; i++)
        {
            memberViews[i].SetHighlight(i == indexA || i == indexB);
        }
    }
}
  • memberViews:並び順の番号と、ロビーの場所を合わせた配列です。0〜2がPartyAreaの3人、3が控えのReserveViewです。場所は動かさずに、そこに立つ人を入れ替えるので、番号がそのまま使えます
  • 1人目・2人目:#19で作ったOnSelectで、一覧で選んでいる人を光らせます。2人目を選んでいる間は、1人目も光らせたままにします。同じ人を選んだり、Escを押したりしたら、1人目を選び直します
  • chosenIndex:ラムダ式(index => ...)の中で使う変数は、あとで呼ばれたときの値が使われます。firstIndexはループで書き換わるので、別の変数に入れておきます
  • SwapAsync:2人を同時に跳ばしたいので、先にHopToAsyncを2つとも始めてから、順にawaitします。着いたらMembersの2人を入れ替えて、ShowPartyで、ロビーの絵・名前・HP・MPを出し直します
  • Hierarchyで、Canvasの外に空のオブジェクトを作り、名前を「PartyMenu」にして、「PartyMenu」スクリプトを付ける
    • List Menuに PartyWindow、Message Windowに MessageWindow、Message Textに MessageText
    • Member Viewsを 4 にして、Stage>PartyAreaの Slime・Fairy・Jiangshi(Lobby MenuのParty Viewsと同じ順番)、最後に ReserveView
    • Lobby Menuに Lobby

LobbyMenu

LobbyのLobbyオブジェクトのInspector。Lobby Menu (Script)のParty Viewsの下にReserve View(ReserveView)、Equip Menuの下にParty Button(PartyButton)・Party Menu(PartyMenu)が増えている
LobbyMenuに「なかま」と控えをつなぐ

LobbyMenuに、「なかま」のボタンと控えの見た目をつなぎます。

partyViewsの下と、equipMenuの下に、欄を足します。

    [SerializeField] private UnitView reserveView;    // 控え(ロビーのすみで本を読んでいる)
    [SerializeField] private Button partyButton;      // なかま
    [SerializeField] private PartyMenu partyMenu;

ShowPartyを、次のように書き換えます。入れ替えると、その場所に立つ人が変わるので、絵と名前も毎回入れ直します。PartyMenuから呼べるようにpublicにします。

    // 仲間の絵・名前・レベル・HP・MP と、お金を表示し直す(倒れている人は、戦闘不能の絵)
    // HP・MP のゲージは、減る演出をせずにそのまま(バトルから戻ってきたとき、満タンから減って見えないように)
    // なかまを入れ替えたときにも呼ぶ
    public void ShowParty()
    {
        GameSession session = GameSession.Instance;
        List<PartyMember> party = session.Party;
        for (int i = 0; i < party.Count; i++)
        {
            PartyMember member = party[i];
            UnitView view = partyViews[i];
            StatusRow row = rows[i];
            view.SetupCharacter(member.Data);
            row.SetName(member.Data.CharacterName);
            row.SetLevel(member.Level);
            row.SetHp(member.Hp, member.Stats.maxHp, true);
            row.SetMp(member.Mp, member.Stats.maxMp, true);
            if (member.IsDead)
            {
                view.ShowDown();
            }
            else
            {
                view.Revive();
            }
        }

        // 控え:本を読んで待っている(いなければ隠す)
        List<PartyMember> reserves = session.Reserves;
        reserveView.gameObject.SetActive(reserves.Count > 0);
        if (reserves.Count > 0)
        {
            PartyMember reserve = reserves[0];
            reserveView.SetupCharacter(reserve.Data);
            if (reserve.IsDead)
            {
                reserveView.ShowDown();
            }
            else
            {
                reserveView.Revive();
                reserveView.ShowReading();
            }
        }
        goldCounter.ShowInstant(session.Gold);
    }
  • 一番上にusing System.Collections.Generic;を足します(Listを使うので)
  • 同じ番号の絵と行を何度も使うので、view・rowに入れてから使います。控えもreserveに入れておきます
  • ShowPartyで絵を入れるようになったので、Startのループは行を作るだけにします。memberは1回しか使わなくなるので、ループの中はrows[i] = statusWindow.AddRow(session.Party[i].Data);の1行にします
  • 倒れたまま控えにした人は、本を読まずに戦闘不能の絵にします

Startで、ボタンが押されたときのメソッドを登録します(equipButtonの下)。

        partyButton.onClick.AddListener(OnPartyClicked);

OnEquipClickedの下に、次のメソッドを足します。#19でまとめたOpenSubMenuを使うので、これだけで済みます。

    private void OnPartyClicked()
    {
        OpenSubMenu(partyMenu.OpenAsync, partyButton);
    }
  • Lobbyオブジェクトの Lobby Menu に、Reserve View(ReserveView)・Party Button(PartyButton)・Party Menu(PartyMenu)を入れる

控えにも経験値を半分

バトルに勝って「てきを ぜんぶ たおした!」「6ポイントの けいけんちを かくとく!」のあと、「ひかえの キョンシーも 3ポイント もらった!」。真ん中に「しょうり!」のウインド
控えのキョンシーにも3ポイント

この節では、バトルに出ていない控えの仲間にも、経験値を分けます。

控えがずっとLv1のままだと、あとで入れ替えたくなっても、弱すぎて使えません・・・。そこで、勝ったときの経験値の半分を、控えももらえるようにします。

PartyMemberのStatsAtLevelの上に、次のメソッドを足します。

    // 経験値をもらう(控えの仲間。バトルに出ている人は BattleUnit.GainExp)。レベルが上がったら true
    public bool GainExp(int amount)
    {
        int oldLevel = Level;
        Stats before = Stats;
        TotalExp += amount;
        if (Level == oldLevel)
        {
            return false;
        }
        Hp += Stats.maxHp - before.maxHp; // 最大HPが増えた分だけ、今のHPも増やす
        Mp += Stats.maxMp - before.maxMp; // MP も同じ
        return true;
    }
  • PartyMemberのLevelとStatsは、経験値から計算しています。なのでTotalExpを足すだけで、レベルも能力も変わります
  • 最大HPが増えた分だけ、今のHPも増やします。バトルでのレベルアップ(#12のBattleUnitのGainExp)と同じ考え方です
  • 覚えるまほうは、バトルの始めにレベルから調べているので、控えの間にレベルが上がっても、次にバトルに出たときに使えます

BattleManagerのShowVictoryAsyncで、立っている仲間が経験値をもらうループのあとに、1行足します。

        await GiveReserveExpAsync(exp / 2);

ShowLevelUpAsyncの上に、次のメソッドを足します。

    // 控えの仲間も、経験値を半分もらう(バトルに出ていなくても、置いていかれないように)
    private async Awaitable GiveReserveExpAsync(int exp)
    {
        if (GameSession.Instance == null || exp <= 0)
        {
            return; // Battle シーンから再生したときは、控えがいない
        }
        foreach (PartyMember member in GameSession.Instance.Reserves)
        {
            if (member.IsDead)
            {
                continue; // 倒れている人は、もらえない(バトルに出ている人と同じ)
            }
            string name = member.Data.CharacterName;
            bool isLevelUp = member.GainExp(exp);
            await messageWindow.ShowAsync($"ひかえの {name}も {exp}ポイント もらった!");
            if (isLevelUp)
            {
                await messageWindow.ShowAsync($"{name}は レベル{member.Level}に あがった!");
            }
        }
    }
  • exp / 2はintどうしの割り算なので、小数は切り捨てです(7なら3)
  • 控えはバトルの画面にいないので、レベルアップの演出は出さずに、メッセージだけにしています

動かして確認!

地下のバトル。メドゥーサが「まほう」→「まほうの矢」で紙ひこうきをねらう。紙ひこうきの こうげき! のあと、紙ひこうきに5の ダメージ!で敵がいなくなり、みんなが喜ぶポーズ
入れ替えたメドゥーサが、バトルでまほうを使う
  • Lobbyシーンを開いて再生する。左の窓ぎわで、メドゥーサが本を読んでいる
  • 「なかま」→ キョンシー → メドゥーサ。2人が跳んで入れ替わり、下のステータスの3行目がメドゥーサになる
  • 「地下へ」で、メドゥーサがバトルに出ている。「まほう」に まほうの矢 がある
  • 勝つと、控えのキョンシーにも経験値の半分が入る(GIFは、確かめやすいように敵を2体にしています。6ポイントの半分で3ポイント)
  • 控えのまま何回か勝つと、控えのレベルも上がる(#12の表で、10ポイントたまるとLv2。「なかま」の一覧の右はしで確かめられる)
入れ替えたあとのロビー。左の窓ぎわでキョンシーが本を読み、真ん中にメドゥーサ。右の一覧は スライム・フェアリー・メドゥーサ・キョンシー(ひかえ Lv1)で、下のステータスの3行目はメドゥーサ HP 28/28・MP 18/18
入れ替えたあと

#20の動作確認

  • ロビーの左の窓ぎわに、控えの仲間が本を読んで立っている
  • 「なかま」で4人の一覧が開き、選んでいる人が白く光る。控えの右はしには「ひかえ」
  • 2人目を選んでいる間は、1人目も光ったまま。同じ人を選ぶかEscで、1人目を選び直す
  • 2人を選ぶと、相手の場所へ跳んで入れ替わる。下のステータスも入れ替わる
  • バトルに出る3人どうしを入れ替えると、並び順(コマンドを選ぶ順番)が変わる
  • 「地下へ」で、上の3人がバトルに出る
  • 勝つと、控えの仲間も経験値の半分をもらう(倒れている控えはもらえない)

あとがき

今回は、4人目のメドゥーサを仲間に入れて、ロビーでバトルに出る3人を入れ替えられるようにしました。並び順の上の3人がバトルに出る、と決めておいたので、バトルの側は何も変えずに済みましたね。これで、ロビーのメニューは「セーブ」以外がそろいました。次回は、地下の階を作って、何回か戦いながら奥へ進めるようにしたいと思います!

スライム

メドゥーサの全体まほうは、レベルが上がってからのお楽しみです・・・

フェアリー

控えにも経験値が入るから、どんどん入れ替えて試してみてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (1件)

コメントする

目次