How do raycasts work?

Raycasts en Unity 2D: La Guía Definitiva

13/08/2007

Valoración: 4.34 (11669 votos)

En el vasto universo del desarrollo de videojuegos con Unity, existen herramientas fundamentales que, una vez dominadas, abren un abanico de posibilidades creativas y funcionales. Una de las más poderosas y versátiles en el entorno 2D es, sin duda, el Raycast. Si alguna vez te has preguntado cómo un personaje sabe que hay suelo bajo sus pies, cómo una bala detecta a un enemigo o cómo un personaje puede "ver" en una dirección específica, es muy probable que la respuesta involucre un Raycast. Es una técnica esencial que simula una línea de visión o un sondeo en el mundo del juego para recopilar información sobre lo que le rodea.

How do raycasts work?
Raycasts are useful for determining lines of sight, targets hit by gunfire and for many other purposes in gameplay. Additionally, this will also detect Collider (s) at the start of the ray. In this case, the ray starts inside the Collider and doesn't intersect the Collider surface.

Conceptualmente, un Raycast es como disparar un rayo láser invisible desde un punto de origen, en una dirección concreta y con una longitud determinada. Si este rayo "choca" o intersecta con un objeto que tenga un componente Collider 2D, el sistema nos devolverá información detallada sobre esa colisión. En este artículo, desglosaremos a fondo el funcionamiento de Physics2D.Raycast, exploraremos sus parámetros, aprenderemos a interpretar sus resultados y veremos un ejemplo práctico para solidificar el conocimiento.

Índice de Contenido

¿Qué es Exactamente un Raycast y Para Qué Sirve?

Imagina que eres un personaje en un juego de plataformas. Para saltar, el juego primero necesita saber si estás tocando el suelo. Una forma muy eficiente de lograrlo es lanzar un Raycast muy corto desde los pies del personaje hacia abajo. Si el rayo impacta con un objeto en la capa "Suelo", entonces el juego sabe que puedes saltar. Este es solo uno de los innumerables usos.

Los Raycasts son la base para mecánicas como:

  • Detección de suelo, paredes y techos: Fundamental para la lógica de movimiento de cualquier personaje.
  • Línea de visión: Permite a los enemigos detectar al jugador si no hay obstáculos entre ellos.
  • Sistemas de disparo: Determinar qué objeto fue alcanzado por una bala (especialmente en juegos con proyectiles instantáneos o "hitscan").
  • Interacciones con el entorno: Detectar objetos con los que el jugador puede interactuar al mirarlos.
  • Puzzles y físicas personalizadas: Crear lásers que rebotan, ganchos de agarre o efectos de levitación.

La gran ventaja del Raycast es su eficiencia. Es una operación de física mucho más barata en términos de rendimiento que, por ejemplo, crear un objeto físico para la detección y comprobar sus colisiones constantemente.

Anatomía de la Función `Physics2D.Raycast`

La función principal que usaremos es Physics2D.Raycast. Aunque tiene varias sobrecargas (versiones con diferentes parámetros), la más común y fundamental es la siguiente:

public static RaycastHit2D Raycast(Vector2 origin, Vector2 direction, float distance, int layerMask);

Vamos a desglosar cada uno de sus parámetros para entenderlos a la perfección. Hemos preparado una tabla para que te sea más fácil consultarlos.

Tabla de Parámetros Principales

ParámetroDescripciónEjemplo de Uso
originEl punto de inicio del rayo en el espacio 2D. Generalmente, la posición de un objeto.transform.position
directionUn vector que indica la dirección en la que se lanzará el rayo. Debe ser un vector normalizado (magnitud de 1).Vector2.down o -transform.up
distanceLa distancia máxima que recorrerá el rayo. Puede ser infinito.1.5f o Mathf.Infinity
layerMaskUn filtro para que el rayo solo detecte colliders en capas específicas. Es crucial para el rendimiento.1 << 8 o LayerMask.GetMask("Enemigos")

Profundizando en los Parámetros

  • Origin (Origen): Es simplemente el punto de partida. Si quieres disparar desde un personaje, usarás su transform.position. Si es desde el cañón de un arma, usarás la posición de un objeto hijo que represente el cañón.
  • Direction (Dirección): Este es el vector que define hacia dónde apunta el rayo. Unity proporciona atajos como Vector2.up, Vector2.down, Vector2.left y Vector2.right. También puedes usar la dirección local de un objeto, como transform.right para apuntar hacia su derecha.
  • Distance (Distancia): Define el alcance del rayo. Si no se especifica, por defecto es Mathf.Infinity, lo que significa que el rayo se extenderá indefinidamente. Sin embargo, por optimización, siempre es mejor usar la distancia más corta que necesites.
  • LayerMask (Máscara de Capa): Este es uno de los parámetros más importantes para la optimización y la lógica del juego. En Unity, puedes asignar objetos a diferentes capas (Layers). Una LayerMask le dice al Raycast en qué capas debe buscar colisiones, ignorando todas las demás. Esto evita que un Raycast para detectar el suelo colisione accidentalmente con el propio jugador, monedas u otros objetos irrelevantes, mejorando drásticamente el rendimiento.

Interpretando los Resultados: El Objeto `RaycastHit2D`

La función Physics2D.Raycast devuelve un objeto de tipo RaycastHit2D. Este objeto contiene toda la información sobre el impacto, si es que hubo uno. Si el rayo no golpea nada, la información que contiene será nula.

La forma más común de usarlo es dentro de una condición `if`:

RaycastHit2D hit = Physics2D.Raycast(origen, direccion, distancia);

if (hit.collider != null) { // O simplemente if(hit)
// ¡Hemos golpeado algo!
}

El objeto `hit` tiene varias propiedades útiles:

  • hit.collider: Devuelve el componente Collider2D del objeto que fue golpeado. Desde aquí puedes acceder a todo lo demás, como hit.collider.gameObject para obtener el objeto del juego, o hit.collider.tag para ver su etiqueta.
  • hit.point: Un Vector2 que representa el punto exacto en el espacio 2D donde el rayo impactó con el collider.
  • hit.normal: Un Vector2 que representa la normal de la superficie en el punto de impacto. Es un vector perpendicular a la superficie, muy útil para calcular rebotes o para saber el ángulo de una pendiente.
  • hit.distance: Un valor `float` que indica a qué distancia del origen se produjo el impacto.
  • hit.transform: Un atajo para acceder directamente al Transform del objeto golpeado (equivalente a `hit.collider.transform`).

Ejemplo Práctico: Creando un Efecto de Flotación para un Personaje

La teoría está muy bien, pero la mejor forma de aprender es con la práctica. A continuación, veremos el código de un script que utiliza un Raycast para hacer que un objeto con un Rigidbody2D flote a una altura constante sobre una superficie, como un vehículo aerodeslizador.

using UnityEngine; public class LevitacionConRaycast: MonoBehaviour { // La altura a la que queremos que el objeto flote. public float alturaFlotacion = 1.5f; // La fuerza que aplicaremos para levantar el objeto. public float fuerzaElevacion = 100f; // Un amortiguador para reducir el rebote y estabilizar el movimiento. public float amortiguacion = 10f; Rigidbody2D rb2D; void Start() { rb2D = GetComponent<Rigidbody2D>(); } void FixedUpdate() { // 1. Lanzamos un rayo hacia abajo desde la posición del objeto. RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up); // 2. Comprobamos si el rayo ha golpeado algo. if (hit.collider != null) { // 3. Calculamos la distancia actual a la superficie y el "error" // respecto a la altura deseada. float distanciaActual = Mathf.Abs(hit.point.y - transform.position.y); float errorAltura = alturaFlotacion - distanciaActual; // 4. La fuerza a aplicar es proporcional al error de altura. // También restamos una parte basada en la velocidad vertical actual // para amortiguar el movimiento y evitar que rebote infinitamente. float fuerzaAplicar = fuerzaElevacion * errorAltura - rb2D.velocity.y * amortiguacion; // 5. Aplicamos la fuerza calculada al Rigidbody2D, empujándolo hacia arriba. rb2D.AddForce(Vector3.up * fuerzaAplicar); } } } 

Este script, añadido a un objeto con un Rigidbody2D, lanzará un rayo hacia abajo en cada ciclo de físicas (`FixedUpdate`). Si detecta una superficie, calculará cuán lejos está de su altura de flotación ideal y aplicará una fuerza correctora hacia arriba. El factor de amortiguación es clave para que el movimiento sea suave y no un rebote constante y violento.

Consejos y Buenas Prácticas

Para sacar el máximo partido a los Raycasts, ten en cuenta estos consejos:

  1. Usa LayerMasks siempre que sea posible: Es la mejora de rendimiento más significativa que puedes hacer. No fuerces a Unity a comprobar colisiones con objetos que no te interesan.
  2. Visualiza tus Raycasts: Durante el desarrollo, es increíblemente útil poder ver tus rayos. Usa la función Debug.DrawRay(origen, direccion * distancia, Color.red) para dibujar una línea en el editor de escena que represente tu Raycast. ¡Te ahorrará horas de depuración!
  3. Elige la distancia adecuada: Evita usar Mathf.Infinity si no es estrictamente necesario. Un rayo más corto es un cálculo más rápido.
  4. Cuidado con el origen: Si el origen del Raycast está dentro de un collider, lo detectará inmediatamente a una distancia de cero. Ten esto en cuenta en tu lógica, especialmente para la detección de suelo si el pivote de tu personaje está en sus pies.

Preguntas Frecuentes (FAQ)

¿Mi Raycast no detecta nada, ¿por qué?
Las causas más comunes son: una dirección incorrecta (un vector no normalizado o que apunta al lugar equivocado), una distancia demasiado corta, el objeto que intentas detectar no tiene un componente Collider2D, o el objeto está en una capa que tu LayerMask está ignorando.
¿Puedo detectar Triggers con un Raycast?
Por defecto, los Raycasts ignoran los colliders marcados como Trigger. Para cambiar este comportamiento, debes ir a `Edit > Project Settings > Physics 2D` y activar la opción `Queries Hit Triggers`.
¿Cuál es la diferencia entre `Raycast` y `RaycastAll`?
`Physics2D.Raycast` se detiene y devuelve información sobre el primer objeto que encuentra. En cambio, `Physics2D.RaycastAll` no se detiene; atraviesa todos los objetos en su camino (hasta la distancia especificada) y devuelve un array con todos los `RaycastHit2D` que encontró. Es útil para mecánicas como balas que atraviesan a varios enemigos.
¿Es mejor usar Raycasts en `Update` o en `FixedUpdate`?
Si el Raycast está relacionado con la física (movimiento, fuerzas, etc.), como en nuestro ejemplo de levitación, debe ir en `FixedUpdate` para mantenerse sincronizado con el motor de físicas. Si es para lógica no física, como una interacción con el ratón o una línea de visión que no afecta al movimiento, `Update` suele ser el lugar adecuado.

Si quieres conocer otros artículos parecidos a Raycasts en Unity 2D: La Guía Definitiva puedes visitar la categoría Juegos.

Subir