0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Unity 3D入門 #15 [敵の配置]

Posted at

NavMeshによってプレイヤーを追いかける敵の設定
参考URL:https://tech.pjin.jp/blog/2020/04/30/unity_navmesh_startup/
ドアを通る参考URL:https://gametukurikata.com/navigation/navmovearea

また、ドアを通るときはドアを開け、通った後にドアを閉めるようにします。

Ray ray1 = new Ray(this.transform.position, -this.transform.forward);
RaycastHit hit1;
if (Physics.Raycast(ray1, out hit1, maxDist){
    // 通ったドアの鍵を閉める
    if (hit1.collider.gameObject.tag == "Door"){
       if(!hit1.collider.gameObject.GetComponent<DoorOpen>().IsLocked){
           if(!hit1.collider.gameObject.GetComponent<DoorOpen>().DoorClosed){
               //ドアが開いている場合、ドアを閉じる
               hit1.collider.gameObject.GetComponent<DoorOpen>().Activate();
           }
           // 鍵が開いている場合、鍵を閉める
           hit1.collider.gameObject.GetComponent<DoorOpen>().IsLocked = true;
       }
    }
}

Ray ray2 = new Ray(this.transform.position, this.transform.forward);
RaycastHit hit2;
if (Physics.Raycast(ray2, out hit2, maxDist)){
    // 通ったドアの鍵を開ける
    if (hit2.collider.gameObject.tag == "Door"){
        // 鍵がしまっている場合、鍵を開ける
        hit2.collider.gameObject.GetComponent<DoorOpen>().IsLocked = false;
        //ドアが閉じている場合、ドアを開ける
        if(hit2.collider.gameObject.GetComponent<DoorOpen>().DoorClosed){
            hit2.collider.gameObject.GetComponent<DoorOpen>().Activate();
        }
    }
}

上のコードにおいて、ドアオブジェクトはDoorOpen.csをアタッチされており、isLockedとisOpenの二つの変数に今のドアの状態を記録している。
isLocked -> true:鍵がかかっている, false:鍵が開いている
isOpen -> true:ドアが開いている, false:ドアが閉まっている

次に、敵がプレイヤーを発見するスクリプトを書きます。

// 半径3以内に近づいたら発見
if(Vector3.Distance(this.transform.position, goal.transform.position) < 3){
    isFind = true;
    isLast = false;
}
// 間に壁がなければ発見
RaycastHit hit;
// ターゲットオブジェクトとの差分を求め
Vector3 temp =  goal.transform.position - this.transform.position;
// 正規化して方向ベクトルを求める
Vector3 normal = temp.normalized;
if (Physics.Raycast (this.transform.position, normal, out hit, maxrange)) {
    if (hit.transform.gameObject == goal) {
        isFind = true;
        isLast = false;
    }else{
        isFind = false;
    }
}

二つの条件「半径3以内に接近」「プレイヤーとの間に壁がなく直線距離がmaxrange以内」の場合に敵はプレイヤーを発見します。
発見した場合、isFindをtrueにし、見失った場合isFindをfalseにします。
isLastは後で使います。

また、プレイヤーを発見した場合はプレイヤーを追いかけますが、プレイヤーを見失った場合も最後にプレイヤーを見た場所まで移動してもらいます。

if(isFind){
    agent.destination = goal.transform.position;
}else{
    agent.destination = goal.transform.position;
    // プレイヤーを最後に発見した場所に行く
    if(!isLast){
        if(Vector3.Distance(this.transform.position, agent.destination) < 3){
            isLast = true;
        }
    }else{
        // 徘徊
    }
}

こう書くことでプレイヤーを見失った地点まで移動するとisLastがtrueになり、「// 徘徊」行動に移ります。

徘徊行動は https://getabakoclub.com/2019/01/09/unityの便利機能を使いこなそう-4-navmeshagentで敵のaiをつくろ/ を参考に実装しました。

public Vector3[] wayPoints = new Vector3[3];//徘徊するポイントの座標を代入するVector3型の変数を配列で作る
private int currentRoot = 0;//現在目指すポイントを代入する変数

void Start () {	
    agent.destination = wayPoints[currentRoot]; // 初期目的地
}

void Update () {	
    if (Vector3.Distance (this.transform.position, wayPoints[currentRoot]) < 1f) {//到着した場合
        Invoke("updateDestination", 3f);
    }
}

void updateDestination(){
    currentRoot = Mathf.FloorToInt(Random.Range (0, wayPoints.Length));
    agent.destination = wayPoints[currentRoot];
}

配列wayPointsに徘徊先目的地を格納し、到着した場合はupdateDestination関数を呼び、目的地を更新する。もちろん目的地までの動きはNavMeshを使用している。

また、敵がどこかに詰まってしまった場合に備えて、同じ場所に5秒以上留まっていたら目的地の更新を行うプログラムを用意する。

private float process_time = 0;
private Vector3 lastPosition;

void Start () {	
    lastPosition = this.transform.position;
}

void Update () {
    // 引っかかったとき、徘徊に戻らせる
    if(lastPosition == this.transform.position){
        process_time += Time.deltaTime;
        if(process_time > 5){
            updateDestination();
            process_time = 0;
        }
    }else{
        process_time = 0;
        lastPosition = this.transform.position;
    }
}

使用しているupdateDestination関数はさらに一つ上のコードに記載してある。

これで大まかに敵AIの設計が終わった。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?