ステルスゲームの緊張感は、 「敵に見つかるかもしれない」 というスリルから生まれます。物陰に隠れ、視線の死角を縫って進む——あの体験の心臓部が、敵の 視界(Field of View)判定 です。でも「見える/見えない」をどう実装すればいいのか、いざとなると悩みます。実は、視界判定は 距離 ・角度・遮蔽の3段階 に分けて考えると、驚くほどシンプルに作れます。
この記事では、敵の視界でプレイヤーを検知する仕組みを組み立てます。距離 で範囲を絞り、角度 で視野コーンを作り、Raycast で壁の遮蔽をチェックする——この3段階の検知ロジックと、発見時の状態遷移、そして Gizmosでの視界の可視化 までを解説します。NavMeshでAIパスファインディング の「追跡」と対をなす、"発見" に特化した1本です。
この記事でわかること
- 視界判定の 3段階(距離 → 角度 → 遮蔽)
- 角度 で視野コーンを作る(
Vector3.Angle)- Raycast で壁の遮蔽をチェックする
- 発見時の 状態遷移(巡回 → 追跡)
- Gizmos で視界を可視化してデバッグする
- 発展:見られ続けると見つかる 警戒度(疑いメーター)
動作確認環境: Unity 6 (6000.x)
視界判定は3段階で考える
「敵にプレイヤーが見えているか」——これを一発で判定しようとすると難しく感じますが、 3つの条件をANDで重ねる と考えると、途端に明快になります。

| 段階 | 判定内容 |
|---|---|
| 1. 距離 | プレイヤーが視界の 届く範囲内 か(近すぎず遠すぎず) |
| 2. 角度 | プレイヤーが 視野角の内側 か(正面のコーンの中) |
| 3. 遮蔽 | 敵とプレイヤーの間に 壁がない か(Raycast) |
この順番で判定するのがポイントです。 軽い判定から順に、ダメなら早期に打ち切る。まず距離(引き算1回で済む)、次に角度、最後にいちばん重いRaycast。「遠すぎるならそもそも角度もRaycastも見ない」と早期リターンすれば、大量の敵がいても軽く動きます。この3つすべてを満たしたときだけ、「プレイヤーが見えた」と判定します。
距離と角度でコーンを作る
まず「距離」と「角度」で、敵の前方に 扇形の視界コーン を作ります。ここが視界判定の骨格です。

using UnityEngine;
public class FieldOfView : MonoBehaviour
{
[SerializeField] private float viewRadius = 8f; // 視界の届く距離
[SerializeField] private float viewAngle = 90f; // 視野角(度)
[SerializeField] private float eyeHeight = 1.6f; // 敵の「目」の高さ
[SerializeField] private float targetHeight = 1.2f; // プレイヤー側の狙う高さ(胸)
[SerializeField] private Transform player;
[SerializeField] private LayerMask obstacleMask; // 壁のレイヤー
public bool CanSeePlayer()
{
// 視線は「足元→足元」ではなく「目→胸」で結ぶ
Vector3 eye = transform.position + Vector3.up * eyeHeight;
Vector3 targetPoint = player.position + Vector3.up * targetHeight;
Vector3 toPlayer = targetPoint - eye;
// (1) 距離:範囲外なら見えない
float distance = toPlayer.magnitude;
if (distance > viewRadius) return false;
// (2) 角度:正面からの角度が視野角の半分を超えたら見えない
float angle = Vector3.Angle(transform.forward, toPlayer);
if (angle > viewAngle / 2f) return false;
// (3) 遮蔽チェックへ(次の節)
return !Physics.Raycast(eye, toPlayer.normalized, distance, obstacleMask);
}
}
角度の判定が肝です。 敵の正面ベクトル(transform.forward)と、敵からプレイヤーへの方向の角度 を Vector3.Angle で測り、それが 視野角の半分以下 なら、プレイヤーはコーンの内側にいます。視野角90度なら、正面から左右45度ずつの範囲が視界、というわけです。距離と角度、この2つだけで「前方の扇形」が定義できます。
なお、eyeHeight と targetHeight は、transform.position が足元にある前提の高さです。標準のCapsuleのように原点が体の中心にあるなら、eyeHeight は 0.6、targetHeight は 0.2 くらいにします。
Raycastで遮蔽をチェックする
距離と角度の条件を満たしても、 間に壁があれば見えない はずです。ステルスゲームの「物陰に隠れる」を成立させるのが、この遮蔽チェックです。

方法は Raycast です。 敵の目からプレイヤーへ向けて光線を撃ち、壁(障害物レイヤー)に当たるかどうか を調べます。
- 壁に当たった → プレイヤーは壁の向こう。