見出し画像

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

前回の記事はこちら
前回はメッセージ関係のクラスを実装し、複数の文字列を画面表示するところまでを行いました。

Array2Dクラスの実装

今回からマップ関連のクラスを作っていきます。手始めにマップのデータ構造を定義します。Array2Dスクリプトを作成しましょう。

public class Array2D
{
   public int width;
   public int height;
   private int[,] data;

   public Array2D(int w, int h)
   {
       width = w; height = h;
       data = new int[width, height];
   }

   /**
   * X/Z座標にある値を取得する
   */
   public int Get(int x, int z)
   {
       if (x >= 0 && z >= 0 && x < width && z < height)
       {
           return data[x, z];
       }
       return -1;
   }

   /**
   * X/Z座標に値(v)を設定する
   */
   public int Set(int x, int z, int v)
   {
       if (x >= 0 && z >= 0 && x < width && z < height)
       {
           data[x, z] = v;
           return v;
       }
       return -1;
   }
}

領域外にアクセスした場合は「-1」を返します。

DirUtilクラスの実装

ところで、PlayerMovementクラスにメソッドが集まり過ぎていますね。ある程度メソッドを切り離した方がいいかもしれません。
そこで方向に関する関数をまとめたDirUtilクラスを作成し、そこに切り離したメソッドを移すことにします。
DirUtilクラスはオブジェクトやコンポーネントではなく、あくまで関数群の集まりなのでstaticなクラスにします。

using UnityEngine;

public static class DirUtil
{
   // 次のメソッドを「public static」にして移して下さい
   /**
   * 入力されたキーに対応する向きを返す
   */
   public static EDir KeyToDir();

   /**
   * 引数で与えられた向きに対応する回転のベクトルを返す
   */
   public static Quaternion DirToRotation(EDir d);

   /**
   * 引数で与えられた回転のベクトルに対応する向きを返す
   */
   public static EDir RotationToDir(Quaternion r);

   /**
   * 現在の座標(position)と移動したい方向(d)を渡すと
   * 移動先の座標を取得
   */
   public static Pos2D GetNewGrid(Pos2D position, EDir d);

}

そして、PlayerMovementで使用している該当関数の前に「DirUtil.」を付けて下さい。

Fieldオブジェクトの作成

床と障害物、プレイヤーを纏めるオブジェクトを作成しましょう。Unityエディターに戻って下さい。
ヒエラルキービューで右クリック→「空のオブジェクトを作成」をクリックします。そして名前を「Field」にして、FloorとPlayerオブジェクトをその階層下に移動して下さい。
FieldとFloorとPlayerオブジェクトの位置を全て0にしましょう。

スクリーンショット 2020-04-28 14.14.45

Fieldクラスの実装その1

Fieldクラスにはフィールド情報の管理をして貰います。それに伴い、PlayerMovementのいくつかのメソッドをこのクラスに移す必要があります。
なお、クラス自体はFieldオブジェクトのコンポーネントとして作成するためstaticにはしません。しかし今から移すメソッドはどこからでもアクセスできるようにしたいので、全てstaticな関数にします。

using UnityEngine;

public class Field : MonoBehaviour
{
   // 次のメソッドを「public static」にして移して下さい
   /**
   * グリッド座標(X)をワールド座標(X)に変換
   */
   public static float ToWorldX(int xgrid);

   /**
   * グリッド座標(Z)をワールド座標(Z)に変換
   */
   public static float ToWorldZ(int zgrid);

   /**
   * ワールド座標(X)をグリッド座標(X)に変換
   */
   public static int ToGridX(float xworld);

   /**
   * ワールド座標(Z)をグリッド座標(Z)に変換
   */
   public static int ToGridZ(float zworld);
}

できたら、PlayerMovementクラスの該当関数の前に「Field.」を付けましょう。
これでPlayerMovementクラスが大分すっきりしました。

本日はここまでにしましょう。次回はFieldクラスに新しいメソッドを追加しようと思います。

おまけ:プレイヤーの位置が小数点になってしまう

はい、またやらかしました。PlayerMovement中のMoveメソッドに以下を追記して下さい。何度もすみません......。

private Pos2D Move(Pos2D currentPos, Pos2D newPos, ref int frame)
{
   /*    省略    */
   if (complementFrame <= frame)
   {
       frame = 0;
       // 次の一行を追記
       transform.position = new Vector3(px2, 0, pz2);
       return newPos;
   }
   return currentPos;
}

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