見出し画像

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

前回の記事はこちら
前回はEDirを定義し、ユニティちゃんをキー操作で自由に動かすところまで行いました。

Pos2Dの定義

少し内容が前後しますが、先に「Pos2D」クラスを定義しておきます。
Scriptsフォルダ内で右クリックして、C#スクリプトを作成、「Pos2D」という名前にします。

/**
* 2次元の座標クラス
*/
[System.Serializable]
public class Pos2D
{
   public int x, z;
}

[System.Serializable]について簡単に説明するならば、このクラスを別のクラスで呼び出した時、その別のクラスからインスペクター上でこのクラスにある内部のパラメーターを編集できるようになる、といった所でしょうか。
説明するとややこしいので、一度試してみましょう。
「PlayerMovement」スクリプトをダブルクリックして下さい。

public Pos2D grid = new Pos2D();

「PlayerMovement」クラスにこのパラメーターを追加しましょう。そしてビルド、Unityエディターの「PlayerMovement」コンポーネントを見てみます。グリッドというパラメーターができています。こんな感じで内部のパラメーターにアクセスできます。

スクリーンショット 2020-04-25 22.25.02

グリッド座標とワールド座標の相互変換

グリッド移動を実装するにあたって、こちらで作成したグリッド座標とゲームオブジェクトの位置(ワールド座標)を相互に変換する必要があります。という訳で「PlayerMovement」スクリプトを開き、このクラスに以下のメソッドを書き加えて下さい。

/**
* グリッド座標をワールド座標に変換
*/
private float ToWorldX(int xgrid)
{
   return xgrid * 2;
}

private float ToWorldZ(int zgrid)
{
   return zgrid * 2;
}

/**
* ワールド座標をグリッド座標に変換
*/
private int ToGridX(float xworld)
{
   return Mathf.FloorToInt(xworld / 2);
}

private int ToGridZ(float zworld)
{
   return Mathf.FloorToInt(zworld / 2);
}

「FloorToInt」は小数点以下の値を切り捨てる関数です。
今回は「ワールド座標×2 = グリッド座標」の計算で値を算出することにしました。

ユニティちゃんをグリッド移動させる

準備が整ったところで、ユニティちゃんをグリッド移動させてみましょう。
まず、以下のパラメーターとメソッドを「PlayerMovement」クラスに書き加えて下さい。

public int maxFrame = 100;

private int currentFrame = 0;
private Pos2D newGrid = null;

/**
* 補完で計算して進む
*/
private Pos2D Move(Pos2D currentPos, Pos2D newPos, ref int frame)
{
   float px1 = ToWorldX(currentPos.x);
   float pz1 = ToWorldZ(currentPos.z);
   float px2 = ToWorldX(newPos.x);
   float pz2 = ToWorldZ(newPos.z);
   frame += 1;
   float t = (float)frame / maxFrame;
   float newX = px1 + (px2 - px1) * t;
   float newZ = pz1 + (pz2 - pz1) * t;
   transform.position = new Vector3(newX, 0, newZ);
   animator.SetFloat(hashSpeedPara, speed, speedDampTime, Time.deltaTime);
   if (maxFrame == frame)
   {
       frame = 0;
       return newPos;
   }
   return currentPos;
}

/**
* 現在の座標(position)と移動したい方向(d)を渡すと
* 移動先の座標を取得
*/
private Pos2D GetNewGrid(Pos2D position, EDir d)
{
   Pos2D newP = new Pos2D();
   newP.x = position.x;
   newP.z = position.z;
   switch (d)
   {
       case EDir.Left:
           newP.x -= 1; break;
       case EDir.Up:
           newP.z += 1; break;
       case EDir.Right:
           newP.x += 1; break;
       case EDir.Down:
           newP.z -= 1; break;
   }
   return newP;
}

そして「Update」メソッドを以下のように書き換えて下さい。

private void Update()
{
   if(currentFrame == 0)
   {
       EDir d = KeyToDir();
       if (d == EDir.Pause)
           animator.SetFloat(hashSpeedPara, 0.0f, speedDampTime, Time.deltaTime);
       else
       {
           direction = d;
           transform.rotation = DirToRotation(direction);
           newGrid = GetNewGrid(grid, direction);
           grid = Move(grid, newGrid, ref currentFrame);
       }
   }
   else grid = Move(grid, newGrid, ref currentFrame);
}

時間がないので説明は省略致します。ご了承下さい(もしわからないところがあればご連絡下さい。すみません......)。
テストプレイをしてみて、以下のようになれば成功です。

グリッド移動


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