見出し画像

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

前回の記事はこちら
前回は敵を固定マップにて自動巡回させました。

ターゲットが近くにいたら追尾する

ターゲット(主にプレイヤー)が近くにいたら敵を追尾させるようにします。EnemyOperationクラスに新しいパラメーターとメソッドを追加し、Operateメソッドを変更して下さい。

// パラメーターを追加
public int detectDistance = 5;

// メソッドを追加
/**
* ターゲットが近くにいるかどうか
*/
private bool DetectTarget(ActorMovement actorMovement)
{
   int distanceX = Mathf.Abs(target.newGrid.x - actorMovement.grid.x);
   int distanceZ = Mathf.Abs(target.newGrid.z - actorMovement.grid.z);
   return distanceX < detectDistance && distanceZ < detectDistance;
}

// メソッドを変更
public override EAct Operate(ActorMovement actorMovement, ActorParamsController actorParam)
{
   if (actorParam.CantAction()) return EAct.TurnEnd;
   if (actorParam.IsConfusion()) return ConfusionActionAI(actorMovement);
   if (DetectTarget(actorMovement)) return AstarActionAI(actorMovement);
   return GoAroundAI(actorMovement);
}

detectDistanceパラメーターはターゲットの検出距離です。この値を増減することで検出のしやすさを変えることができます。
テストしてみます。敵を近くに置いた状態と遠くに置いた状態を見比べてみます。

スクリーンショット 2020-06-11 18.26.02

初期位置

スクリーンショット 2020-06-11 18.26.52

10歩程度歩いた位置

上の敵はプレイヤーを追いかけていますが、下の敵はプレイヤーを認識していないので反対の方向に進みました。

自動生成されたダンジョンにマーキングする

この巡回AIを自動生成されたダンジョンにも適用したいと思います。
その為に自動生成されたダンジョンにマーキングします。
LoadFieldMapスクリプトを開き、RandomDungeonクラスのメソッドを変更します。

private void CreateHorizontalRoad(Area2D area1, Area2D area2, Field field)
{
   int y1 = Random.Range(area1.room.top, area1.room.bottom);
   int y2 = Random.Range(area2.room.top, area2.room.bottom);
   for (int x = area1.room.right; x < area1.outLine.right; x++)
       data.Set(x, y1, 0);
   for (int x = area2.outLine.left; x < area2.room.left; x++)
       data.Set(x, y2, 0);
   for (int y = Mathf.Min(y1, y2), end = Mathf.Max(y1, y2); y <= end; y++)
       data.Set(area1.outLine.right, y, 0);
   field.SetObject("Connection", "Connection", area1.room.right, y1);
   field.SetObject("Connection", "Connection", area1.outLine.right, y1);
   field.SetObject("Connection", "Connection", area2.room.left, y2);
   field.SetObject("Connection", "Connection", area2.outLine.left - 1, y2);
}

private void CreateVerticalRoad(Area2D area1, Area2D area2, Field field)
{
   int x1 = Random.Range(area1.room.left, area1.room.right);
   int x2 = Random.Range(area2.room.left, area2.room.right);
   for (int y = area1.room.bottom; y < area1.outLine.bottom; y++)
       data.Set(x1, y, 0);
   for (int y = area2.outLine.top; y < area2.room.top; y++)
       data.Set(x2, y, 0);
   for (int x = Mathf.Min(x1, x2), end = Mathf.Max(x1, x2); x <= end; x++)
       data.Set(x, area1.outLine.bottom, 0);
   field.SetObject("Connection", "Connection", x1, area1.room.bottom);
   field.SetObject("Connection", "Connection", x1, area1.outLine.bottom);
   field.SetObject("Connection", "Connection", x2, area2.room.top);
   field.SetObject("Connection", "Connection", x2, area2.outLine.top - 1);
}

private void CreateRoads(Field field)
{
   for (int i = 0; i < areas.Count - 1; i++)
   {
       if (areas[i].outLine.right < areas[i + 1].outLine.left)
           CreateHorizontalRoad(areas[i], areas[i + 1], field);
       if (areas[i + 1].outLine.right < areas[i].outLine.left)
           CreateHorizontalRoad(areas[i + 1], areas[i], field);
       if (areas[i].outLine.bottom < areas[i + 1].outLine.top)
           CreateVerticalRoad(areas[i], areas[i + 1], field);
       if (areas[i + 1].outLine.bottom < areas[i].outLine.top)
           CreateVerticalRoad(areas[i + 1], areas[i], field);
   }
   for (int i = 0; i < areas.Count - 2; i++)
   {
       if (Random.Range(0, 2) == 0) continue;
       if (areas[i].outLine.right < areas[i + 2].outLine.left)
           CreateHorizontalRoad(areas[i], areas[i + 2], field);
       if (areas[i + 2].outLine.right < areas[i].outLine.left)
           CreateHorizontalRoad(areas[i + 2], areas[i], field);
       if (areas[i].outLine.bottom < areas[i + 2].outLine.top)
           CreateVerticalRoad(areas[i], areas[i + 2], field);
       if (areas[i + 2].outLine.bottom < areas[i].outLine.top)
           CreateVerticalRoad(areas[i + 2], areas[i], field);
   }
}

public Array2D Create(int w, int h, Field field, int[] eNum, int[] iNum)
{
   /*   省略   */
   SetObjects(field);
   CreateRoads(field); // ここを変更
   return data;
}

テストしてみます。

スクリーンショット 2020-06-11 20.35.16

スクリーンショット 2020-06-11 20.35.57

ちゃんとマーキングされていますね!

という訳で、今回はここまでです。
次回は敵をランダム配置していきたいと思います。


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