🎮 UnityDocs

Percepción de IA: campo de visión y línea de vista

Cómo hacer que un enemigo detecte al jugador de forma creíble: rango, cono de visión (ángulo) y línea de vista con raycast para que no vea a través de las paredes. La base de un sigilo que funciona.

📄 ArtículoAvanzado✅ RevisadoUnity 6.0 LTSActualizado 2026-07-15
DificultadConceptual Código Matemáticas
Tiempo📖 Lectura 8 min · ⌨️ Práctica 30 min

El problema#

Un enemigo que persigue al jugador en cuanto está cerca (solo por distancia) resulta tonto: te ve a través de las paredes y por la espalda. Una percepción creíble combina tres comprobaciones: rango, ángulo (cono de visión) y línea de vista (que no haya nada en medio).

Las tres preguntas de la visión
  1. ¿Está suficientemente cerca? (rango)
  2. ¿Está dentro del cono de visión, no a mi espalda? (ángulo)
  3. ¿Hay algo tapándolo entre él y yo? (línea de vista)

Solo si las tres son "sí", el enemigo ve al jugador.

La implementación#

C#
using UnityEngine;

public class VisionEnemigo : MonoBehaviour
{
    [SerializeField] private float radio = 12f;
    [SerializeField, Range(0, 360)] private float angulo = 90f;   // apertura del cono
    [SerializeField] private LayerMask capaJugador;
    [SerializeField] private LayerMask capaObstaculos;
    [SerializeField] private Transform ojos;   // desde dónde "mira" (la cabeza)

    public Transform JugadorVisible { get; private set; }

    public bool PuedeVerAlJugador()
    {
        // 1) RANGO: ¿hay un jugador dentro del radio?
        Collider[] enRango = Physics.OverlapSphere(ojos.position, radio, capaJugador);
        if (enRango.Length == 0) { JugadorVisible = null; return false; }

        Transform objetivo = enRango[0].transform;
        Vector3 dir = (objetivo.position - ojos.position).normalized;

        // 2) ÁNGULO: ¿está dentro del cono de visión?
        if (Vector3.Angle(ojos.forward, dir) > angulo / 2f)
        {
            JugadorVisible = null;
            return false;
        }

        // 3) LÍNEA DE VISTA: ¿hay un obstáculo en medio?
        float distancia = Vector3.Distance(ojos.position, objetivo.position);
        if (Physics.Raycast(ojos.position, dir, distancia, capaObstaculos))
        {
            JugadorVisible = null;
            return false;   // algo tapa al jugador
        }

        JugadorVisible = objetivo;
        return true;
    }
}
Dividimos el ángulo entre 2

angulo es la apertura total del cono. Vector3.Angle mide desde el centro (el forward) hacia el objetivo, así que comparamos con la mitad. Un cono de 90° significa 45° a cada lado.

Dibujar el cono en el editor#

Ver el cono en la vista Scene ayuda muchísimo a ajustarlo. Con Gizmos (editor scripting):

C#
void OnDrawGizmosSelected()
{
    if (ojos == null) return;
    Gizmos.color = Color.yellow;
    Gizmos.DrawWireSphere(ojos.position, radio);

    Vector3 izq = Quaternion.Euler(0, -angulo / 2f, 0) * ojos.forward;
    Vector3 der = Quaternion.Euler(0,  angulo / 2f, 0) * ojos.forward;
    Gizmos.color = Color.red;
    Gizmos.DrawRay(ojos.position, izq * radio);
    Gizmos.DrawRay(ojos.position, der * radio);
}

Conectarlo con el comportamiento#

La percepción decide; el comportamiento actúa. Combínala con una máquina de estados: el enemigo patrulla hasta que PuedeVerAlJugador() es true, entonces pasa a Perseguir (con NavMesh). Al perderlo de vista, tras unos segundos, vuelve a patrullar por su última posición conocida.

No comprobar cada frame

Lanzar la comprobación completa (con su raycast) cada fotograma para muchos enemigos es caro. Hazlo cada 0,2 s con una corrutina o un temporizador: la IA no necesita "ver" 60 veces por segundo, y el ahorro es notable con muchos enemigos.

Mejoras habituales#

  • Oído: además de ver, reaccionar a ruidos (disparos, pasos) con un radio de sonido.
  • Memoria: recordar la última posición vista y buscar ahí antes de rendirse.
  • Detección gradual: una barra que se llena mientras te ve (como en los juegos de sigilo) en vez de detección instantánea.
  • Percepción por capas: distinta visión de día/noche, o reducida entre humo.

Errores frecuentes#

  • Detectar solo por distancia (ve a través de paredes y por la espalda).
  • Olvidar el raycast de línea de vista (la parte que da credibilidad).
  • Comparar con el ángulo completo en vez de la mitad.
  • Lanzar la comprobación cada frame para decenas de enemigos (coste innecesario).
  • Poner los "ojos" en los pies del enemigo y que un escalón le tape la visión.

Ponte a prueba#

📝 Pon a prueba lo aprendido

Resumen#

Una percepción creíble combina rango (OverlapSphere), ángulo de un cono de visión (Vector3.Angle contra la mitad de la apertura) y línea de vista (Raycast a obstáculos, para no ver a través de paredes). Dibuja el cono con Gizmos, comprueba cada ~0,2 s en vez de cada frame, y conéctala a una máquina de estados + NavMesh para patrullar, perseguir y buscar.

Fuentes y para profundizar