Raycastで視界に入ったら追いかけるようにする【Unity】

前回、NavMeshで敵はプレイヤーを追いかけるようにしましたが、このままだとどこまでもプレイヤーを追い続ける仕様なので、追いかける際の条件を付加していきます。

Raycastで視界に入ったら追いかけるようにする【Unity】

アクションゲームには障害物が付き物です。

今回は、Raycastを使ってプレイヤーと敵の2点間に壁などの障害物がある場合は、視界から外れるということで、敵はプレイヤーを見失うことにします。

また、それ以外の状態では常に追いかけ続けるようになっているので、敵にSphere Colliderをアタッチして、一定範囲内かつ障害物で視界を遮られていない場合に追いかけるようにします。

敵にSphere Colliderを設定する

Sphere Collider

敵オブジェクトに、一定範囲内に入った事を検知するためのSphere Colliderをアタッチします。

Radiusは「5」にしています。

Is Triggerにチェックを入れておきます。

スクリプトを修正する

敵の行動スクリプトを修正します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class SlimeController : MonoBehaviour
{
//public Transform target;
private NavMeshAgent agent;
//public float speed = 0.01f;
public GameObject damageeffect;
private RaycastHit hit;
//Vector3 SlimePos;
//Rigidbody rigid;
void Start()
{
// SlimePos = transform.position;
// rigid = GetComponent<Rigidbody>();
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
// transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position - transform.position), 0.3f);
// transform.position += transform.forward * this.speed;
// rigid.MovePosition(transform.position + transform.forward * Time.deltaTime);
// transform.rotation = Quaternion.LookRotation(transform.position - SlimePos);
// SlimePos = transform.position;
//transform.rotation = Quaternion.LookRotation(new Vector3(0, 90, 0));
}
private void OnTriggerStay(Collider other)
{
if (other.CompareTag("Player"))
{
GameObject Target = GameObject.Find("SDunitychan");
var diff = Target.transform.position - transform.position;
var distance = diff.magnitude;
var direction = diff.normalized;
if(Physics.Raycast(transform.position, direction, out hit, distance))
{
if(hit.transform.gameObject == Target)
{
agent.isStopped = false;
agent.destination = Target.transform.position;
}
else
{
agent.isStopped = true;
}
}
}
}
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Player")
{
foreach(ContactPoint point in other.contacts)
{
GameObject effect = Instantiate(damageeffect) as GameObject;
effect.transform.position = (Vector3)point.point;
}
}
}
}
view raw SlimeController hosted with ❤ by GitHub

範囲内に入ってくるオブジェクトは、プレイヤーとは限らないので、プレイヤーの場合は「Player」タグで識別するようにします。

プレイヤーが範囲内に入ったら、2点間のベクトル等を計算します。

Rayはゲーム上では見えない光線のようなものです。Raycastを使う事で、この光線に衝突したコライダの情報を取得することで、障害物なのかプレイヤーなのか判断します。

ヒットしたコライダがプレイヤーなのかをif文でチェックし、プレイヤーの場合のみ敵は追いかけるようにします。

それ以外なら「agent.isStopped = true;」でナビゲーションを止めるようにします。

スクリプトを保存したらゲームを実行してみます。

Unityちゃんが壁に隠れた際は、敵の動きもちゃんと止まっていますね。

Raycastは、便利な機能ですが使いすぎると処理が重くなるので気をつけましょう。