見出し画像

【Unity】3Dローグライクゲームの作り方〜Step12-4〜

前回の記事はこちら
前回は階段の位置をセーブできるようにし、階段メニューの外形を作成しました。

シーケンス図・改:階段メニュー

階段メニューを表示する前に、整理のために階段メニューを加えたシーケンス図を作成しましょう。

シーケンス図・改:階段メニュー

階段メニューはプレイヤーが移動した時かつ全員が行動し終わった後に表示されます。つまりターンエンド直前に足下に階段があるかどうか確認すれば良いということですね。

プレイヤーと階段が重なっているか

シーケンス図を書いて確認ができた所で、階段メニューを表示していきたいと思います。
しかしその前に、Fieldクラスにプレイヤーと階段が重なっているかどうかを判定するメソッドを追加します。

/**
* 階段とプレイヤーが重なっているかどうか
* 上り階段(ゴール地点)なら0、下り階段(スタート地点)なら1
* 階段と重なっていなければ-1を返す
*/
public int PlayerOnStairs()
{
   Pos2D pPos = playerMovement.grid;
   for (int i = 0; i < 2; i++)
   {
       Pos2D sPos = stairs.GetComponentsInChildren<ObjectPosition>()[i].grid;
       if (pPos.x == sPos.x && pPos.z == sPos.z) return i;
   }
   return -1;
}

階段メニューを表示する

まずはStairsMenuActionスクリプトを作成して、以下を記述して下さい。

using UnityEngine;

public class StairsMenuAction : MonoBehaviour
{
   public SubMenu subMenu;
   public float inputHoldDelay = 0.3f;
   public Field field;

   private EAct action = EAct.KeyInput;
   private float inputTime = 0;

   // 独自の更新メソッド
   public void Proc()
   {
       switch (action)
       {
           case EAct.KeyInput: KeyInput(); break;
           case EAct.ActBegin: ActBegin(); break;
           case EAct.Act: Act(); break;
           case EAct.ActEnd: ActEnd(); break;
           case EAct.TurnEnd: TurnEnd(); break;
       }
   }

   /**
   * 現在の行動状態を返す
   */
   public EAct GetAction() => action;

   /**
   * 選択するサブメニューの項目を変更する
   */
   private bool MoveSelectSubMenuItem()
   {
       if (Input.anyKeyDown)
       {
           inputTime = 0;
           if (Input.GetKeyDown(KeyCode.UpArrow)) return subMenu.MoveSelect(EDir.Up);
           if (Input.GetKeyDown(KeyCode.DownArrow)) return subMenu.MoveSelect(EDir.Down);
       }
       inputTime += Time.deltaTime;
       if (inputTime < inputHoldDelay) return true;
       if (!Input.anyKey) return true;
       inputTime = 0;
       if (Input.GetKey(KeyCode.UpArrow)) return subMenu.MoveSelect(EDir.Up);
       if (Input.GetKey(KeyCode.DownArrow)) return subMenu.MoveSelect(EDir.Down);
       return true;
   }

   /**
   * サブメニューの項目を選択
   */
   private void SelectSubMenuItem()
   {
       if (Input.anyKeyDown && Input.GetKeyDown(KeyCode.Space))
       {
           action = EAct.Act;
           Hide();
       }
   }

   /**
   * メニューを開く
   */
   private void Show(int isOnStairs)
   {
       if (isOnStairs < 0) return;
       string choiceOrder = "Remain";
       if (isOnStairs == 0) choiceOrder += ", UpStairs";
       else choiceOrder += ", DownStairs";
       subMenu.SetChoices(choiceOrder);
       subMenu.Show();
       gameObject.SetActive(true);
       action = EAct.ActBegin;
   }

   /**
   * メニューを閉じる
   */
   private void Hide()
   {
       gameObject.SetActive(false);
   }

   /**
   * 待機中
   */
   private void KeyInput()
   {
       Show(field.PlayerOnStairs());
   }

   /**
   * アクションを始める
   */
   private void ActBegin()
   {
       MoveSelectSubMenuItem();
       SelectSubMenuItem();
   }

   /**
   * アクション中
   */
   private void Act()
   {
       if (Input.GetKeyUp(KeyCode.Space)) action = EAct.ActEnd;
   }

   /**
   * アクションが終わった
   */
   private void ActEnd()
   {
       action = EAct.TurnEnd;
   }

   /**
   * ターンが終わった
   */
   private void TurnEnd()
   {
       action = EAct.KeyInput;
   }
}

すぐ攻撃してしまうのを防ぐため、スペースキーが入力されてから離されるまでactionがActから変更されないようにしました。
次にSequenceManagerクラスにパラメーターを追加し、Updateメソッドを変更します。

// パラメーターを追加
public StairsMenuAction stairsMenuAction;

// メソッドを変更
void Update()
{
   /*   省略   */
   if (pAct == EAct.ActEnd && !isEnemyDeterminedBehaviour)
   {
       /*   省略   */
   }
   if (actEnemies.Count < 1 && moveEnemies.Count < 1 && pAct == EAct.MoveEnd)
   {
       stairsMenuAction.Proc();
       if (stairsMenuAction.GetAction() == EAct.KeyInput)
           AllOperatedProc(false);
       else 
       {
           playerAction.StopWalkingAnimation();
           AllEnemyStopWalkingAnimation();
       }
       return;
   }
   if (actEnemies.Count < 1 && moveEnemies.Count < 1 && pAct == EAct.ActEnd)
   {
       AllOperatedProc(iAct == EAct.ActEnd);
       return;
   }
   if (pAct == EAct.MoveBegin)
   {
       /*   省略   */
   }
   /*   省略   */
}

ビルドしたら、StairsWindowにStairsMenuActionスクリプトをアタッチして下さい。
テストしてみます。以下のように階段メニューが表示されたらOKです。

スクリーンショット 2020-05-29 22.38.03

スクリーンショット 2020-05-29 22.38.38

という訳で、今回はここまでです。
次回は「階段を上る」や「下りる」を選んだときにプレイヤーを階段に戻したいと思います。

この記事が気に入ったらサポートをしてみませんか?