【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パラメーターはターゲットの検出距離です。この値を増減することで検出のしやすさを変えることができます。
テストしてみます。敵を近くに置いた状態と遠くに置いた状態を見比べてみます。
初期位置
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;
}
テストしてみます。
ちゃんとマーキングされていますね!
という訳で、今回はここまでです。
次回は敵をランダム配置していきたいと思います。
この記事が気に入ったらサポートをしてみませんか?