見出し画像

【Unity】3Dローグライクゲームの作り方〜Step9&10-3〜

前回の記事はこちら
前回はマップデータからアイテムの位置を取得したり、アイテムを保存・読み込みできるようにしたりしました。

シーケンス図・改:インベントリ

今回からインベントリの実装に入ります。ですがその前に、整理も兼ねて、インベントリの操作を加えたシーケンス図を作成します。

シーケンスインベントリ

ざっとこんなものでしょうか。皆様も一度描いてみて下さい。

インベントリウィンドウの作成

早速インベントリを開く動作をさせようと思うのですが、肝心のインベントリを表示するウィンドウがありません。なので、作成していきたいと思います。
因みに今回作成するインベントリは以下のような形を想定しています。

インベントリウィンドウ

あえて少し変わった形のインベントリにすることにしました。もしかしたら途中で変更するかもしれませんが、ひとまずはこんな感じになるというイメージを持ってもらえたらと思います。
ということで外形から作っていきましょう。まず最初にヒエラルキータブ内のCanvasオブジェクトの階層下に空のオブジェクトを作成し、名前を「InventoryWindow」にします。そして、以下の画像のように設定します。

スクリーンショット 2020-05-08 18.54.46

次にInventoryWindowの子オブジェクトとして、「UI→Panel」を作成して下さい。そして、以下のように設定します。

スクリーンショット 2020-05-09 7.01.28

ScrollViewオブジェクトの階層下に空のオブジェクトを配置します。そして、以下のように設定して下さい。

スクリーンショット 2020-05-09 7.07.00

ViewPortオブジェクトの階層下に空のオブジェクトを配置します。このオブジェクトを選択した状態で、インスペクタータブ内の「コンポーネントを追加」→「レイアウト」→「Horizontal Layout Group」を選択して下さい。そして以下のように設定します。

スクリーンショット 2020-05-09 7.19.38

(子を整列パラメータは「Middle Center」にしておきましょう)
次にContentオブジェクトの子オブジェクトとして、「UI」→「Panel」を作成し、以下のように設定します。

スクリーンショット 2020-05-09 7.23.51

その子オブジェクトに「UI」→「Text」を作成し、以下のように設定します。

スクリーンショット 2020-05-08 18.31.25

後は色はお好みで変えて下さい。最終的に以下のようになればOKです。

スクリーンショット 2020-05-09 7.26.00

そして、このItemSlotオブジェクトはプレハブ化してヒエラルキータブ内からは削除し、InventoryWindowオブジェクトは非アクティブにしておきましょう。

インベントリを開く・閉じる

それではスクリプトを書いていきたいと思います。まず「InventoryAction」スクリプトを作成し、以下のように記述します。

using UnityEngine;

public class InventoryAction : MonoBehaviour
{
   private EAct action = EAct.KeyInput;
   private bool isOpen = false;

   // 独自の更新メソッド
   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.MoveBegin: MoveBegin(); break;
           case EAct.Move:      Move();      break;
           case EAct.MoveEnd:   MoveEnd();   break;
           case EAct.TurnEnd:   TurnEnd();   break;
       }
   }

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

   /**
   * 待機中
   */
   private void KeyInput()
   {
       if (Input.anyKeyDown && Input.GetKeyDown(KeyCode.E))
       {
           action = EAct.MoveBegin;
       }
   }

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

   /**
   * アクション中
   */
   private void Act()
   {
       
   }

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

   /**
   * 移動を始める
   */
   private void MoveBegin()
   {
       isOpen = !isOpen;
       if (isOpen) gameObject.SetActive(true);
       action = EAct.Move;
   }

   /**
   * 移動中
   */
   private void Move()
   {
       action = EAct.MoveEnd;
   }

   /**
   * 移動が終わった
   */
   private void MoveEnd()
   {
       if (isOpen) action = EAct.ActBegin;
       else
       {
           gameObject.SetActive(false);
           action = EAct.TurnEnd;
       }
   }

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

次に、SequenceManagerスクリプトを開いて下さい。以下のように追記します。

// 以下のパラメーターを追加
public InventoryAction inventoryAction;

// Updateメソッドを以下のように変更
void Update()
{
   EAct iAct = inventoryAction.GetAction();
   if (iAct != EAct.KeyInput)
   {
       inventoryAction.Proc();
       return;
   }
   EAct pAct = playerAction.GetAction();
   if (pAct == EAct.KeyInput || pAct == EAct.ActBegin || pAct == EAct.Act)
   {
       inventoryAction.Proc();
/*      省略      */

Eキーでインベントリを開き、閉じます。また、インベントリを開いている時に移動や攻撃をしようとしてもできないようになっているかも確認しておきましょう。

(オプション)インベントリのアニメーション

このままでもいいのですが、それだけだと味気ないのでインベントリに軽くアニメーションを付けたいと思います。
「InventoryAnimation」スクリプトを作成し、以下を記述します。

using UnityEngine;

public class InventoryAnimation : MonoBehaviour
{
   public float maxPerFrameOpen = 0.3f;
   public float maxPerFrameClose = 0.3f;

   private Vector3 prevPos;
   private int frame = 0;

   // Start is called before the first frame update
   void Start()
   {
       prevPos = transform.position += new Vector3(0, -300);
   }

   /**
   * 開くアニメーション
   */
   public bool Open()
   {
       return Move(prevPos + new Vector3(0, 300), maxPerFrameOpen);
   }

   /**
   * 閉じるアニメーション
   */
   public bool Close()
   {
       return Move(prevPos + new Vector3(0, -300), maxPerFrameClose);
   }

   /**
   * 補完で計算してアニメーションさせる
   */
   private bool Move(Vector3 p2, float maxPerFrame)
   {
       frame += 1;
       float c = maxPerFrame / Time.deltaTime;
       float t = frame / c;
       transform.position = prevPos + (p2 - prevPos) * t;
       if (c <= frame)
       {
           frame = 0;
           transform.position = p2;
           prevPos = p2;
           return true;
       }
       return false;
   }
}

これをInventoryWindowにアタッチしておきます。
そしてInventoryActionスクリプトを以下のように変更して下さい。

// 以下のパラメーターを追加
public InventoryAnimation anim;

// 以下のように変更
private void Move()
{
   if (isOpen)
   {
       if (anim.Open())
       {
           action = EAct.MoveEnd;
           return;
       }
   }
   else
   {
       if (anim.Close())
       {
           action = EAct.MoveEnd;
           return;
       }
   }
   action = EAct.Move;
}

テストプレイしてみて、以下のようになればOKです。

インベントリ開け閉め

という訳で今回はこれで終了致します。
次回はキャラクターにアイテムを持たせられるようにしてみたいと思います。

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