つい先日、🔍NavMeshで敵キャラが自キャラを追跡するようにするというエントリーで、感知用コリジョンを使って「プレイヤーが一定距離に近づいたら敵が反応する」というロジックを紹介しました。感知用コリジョンに侵入したら問答無用で反応しますので、敵の背後から近づこうがお構いなしでした。
今度は敵に「視野」の概念を導入して、敵の視界に入ったら感知するという風に改造したいと思います。
敵の視野を実装する
感知用コリジョンのおさらい
考え方として、敵キャラの子オブジェクトとして配置した「感知用コリジョン」に接触したコリジョンの持ち主(この場合プレイヤー)を特定します。
●前回行った手順
・敵キャラの子オブジェクトとして「CollisionDetector」を追加
・CollisionDetectorにSphireColliderをアタッチ
・On Trigger Stayにオブジェクトと関数を指定
敵の感知用コリジョン(Sphire Collider)の範囲内に入ると、そのコリジョンにアタッチされている CollisionDetector.cs から EnemyMove.cs に処理が渡され、OnDetectObject関数によってプレイヤーを感知します。
EnemyMove.csの改造箇所
CollisionDetector.csはEnemyMove.csへの橋渡しをするだけなので修正しません。改造箇所はEnemyMove.csのみです。
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class EnemyMove : MonoBehaviour
{
[SerializeField] float searchAngle = 130f;
private NavMeshAgent _agent;
void Start()
{
_agent = GetComponent();
}
public void OnDetectObject(Collider collider)
{
// 検知オブジェクトがPlayerなら追いかける
if (collider.CompareTag("Player"))
{
var positionDiff = collider.transform.position - transform.position; // 自身(敵)とプレイヤーの距離
var angle = Vector3.Angle(transform.forward, positionDiff); // 敵から見たプレイヤーの方向
if (angle <= searchAngle)
{
_agent.destination = collider.transform.position;
}
}
}
}
searchAngle が敵の視野になります。サンプルでは片側130度という指定ですので合計260度の視野になります。
angle が敵の正面から見たプレイヤーの角度です。正面にいる場合は0度ということになります。
angle が searchAngle(視野)の範囲内なら感知となります。
見やすくするために OnDrawGizmos() で色を付けました。
赤い範囲が敵の視界です。
画面右上のチンチクリンな物体がプレイヤーです。
近づいてみます。
敵のSphire Collisionの範囲中にStayしていますが、angle=180の位置にプレイヤーがいるため敵は反応しません。
画面手前側に回り込んでみます。
感知して襲ってきました。
以上となります。
さらに「視界から外れても1秒は追い続ける」「障害物に視線を遮られたら感知から外れる」「見失ったら元の位置に戻る」など様々な改善をすることで、さらにリアルで面白いゲームになっていくと思いますが、今回はここまでとします。