Delta Time en Videojuegos

En este artículo explicaremos qué es el Delta Time o Tiempo Delta en el desarrollo de videojuegos, así como sus ventajas e inconvenientes.

En el desarrollo de videojuegos, la tasa de fotogramas por segundo (FPS) es un aspecto importante para garantizar una buena experiencia de juego. Sin embargo, es bien sabido que, en ocasiones, factores como el hardware, el software en segundo plano o la conexión a Internet pueden hacer que la tasa de fotogramas no se mantenga estable, provocando los llamados «tirones» o lag.

Una de las formas de mitigar los efectos de las caídas de FPS en videojuegos y lograr que el juego se perciba más fluido es mediante el uso del Delta Time. Este método permite ajustar el movimiento y la lógica del juego en función del tiempo transcurrido entre cada fotograma, reduciendo así los efectos negativos de una tasa de fotogramas variable.

¿Qué es el Delta Time?

El Delta Time o Tiempo Delta en videojuegos es el intervalo de tiempo transcurrido entre un fotograma y el siguiente. Se mide en segundos o milisegundos y se usa para ajustar el movimiento, las animaciones y la física del juego de manera proporcional al tiempo real, evitando que los cambios en la tasa de fotogramas (FPS) afecten la jugabilidad.

En un mundo ideal, un videojuego se ejecutaría a una tasa de FPS constante, por ejemplo 60 FPS, donde cada fotograma se dibuja en 1/60 = 0.016 segundos. Sin embargo, en la práctica, los FPS pueden fluctuar debido a la carga del sistema, el hardware o el software en segundo plano, provocando caídas a 50, 45 o 30 FPS.

Imagina un juego en el que un objeto se mueve 5 píxeles cada fotograma. Si el juego se ejecuta a 60 FPS, esto resulta en 300 píxeles por segundo (5 píxeles * 60 fotogramas). Pero, si el juego baja a 30 FPS debido a una caída de rendimiento, ese objeto solo se movería 150 píxeles por segundo (5 píxeles * 30 fotogramas), haciendo que se vea mucho más lento.

Para evitar que estas variaciones afecten el comportamiento de los videojuegos, el Delta Time se calcula dinámicamente para cada fotograma. Se obtiene midiendo el tiempo transcurrido entre el fotograma anterior y el actual, permitiendo ajustar los movimientos y animaciones en función del tiempo real, en lugar de depender de una tasa de FPS fija.

FPS con Tiempo Delta

Supongamos que un objeto debe moverse 100 píxeles por segundo. Si el juego mantiene 60 FPS, cada fotograma ocurre en 1/60 = 0.016 segundos, por lo que el objeto se moverá:
100 × 0.016 = 1.6 píxeles por fotograma.

Ahora, si los FPS bajan a 30 FPS cada fotograma ocurre en 1/30 = 0.033 segundos, y el movimiento se ajustará automáticamente:
100 × 0.033 = 3.3 píxeles por fotograma.

Con el Delta Time conseguimos que, aunque el número de FPS varíe, la velocidad del objeto se mantenga aproximadamente constante.

Cálculo del Tiempo Delta

Los motores de videojuegos como Unity, Godot o Unreal Engine, el Delta Time ya está integrado en la función de actualización de cada fotograma. En JavaScript, podemos calcularlo manualmente mediante una clase estática como la siguiente:

class Time {

  // Guardamos tiempo del fotograma anterior y el delta time actual
  static last_Time = 0;
  static delta_Time = 0;

  // Inicializa temporizador. 
  // Debe llamarse una sola vez justo antes de empezar el bucle principal
  static init() {
    this.last_Time = performance.now();
    this.delta_Time = 0;
  }

  // Actualiza el Delta Time. 
  // Debe llamarse al principio de cada fotograma dentro del bucle principal
  static update() {
    // Obtenemos tiempo actual
    const currentTime = performance.now();

    // Calculamos diferencia en milisegundos y pasamos a segundos
    this.delta_Time = (currentTime - this.last_Time) / 1000;
    this.last_Time = currentTime;

    // Seguridad: Evita saltos gigantescos
    if (this.delta_Time > 0.1) {
      this.delta_Time = 0.1;
    }
  }

  // Devuelve el tiempo transcurrido entre el fotograma anterior y el actual (en segundos).
  static deltaTime() {
    return this.delta_Time;
  }
}

En esta clase usaremos performance.now(), que devuelve el tiempo actual en milisegundos con alta precisión. Para videojuegos en JavaScript, el Delta Time se obtiene restando el tiempo del último fotograma al tiempo actual, asegurando que los cálculos sean proporcionales al tiempo real.

El límite if (this.delta_Time > 0.1) no intenta recuperar todo el tiempo perdido, sino evitar que una pausa o una caída extrema de rendimiento produzca un salto excesivo en el movimiento o la física.

Uso del Tiempo Delta

Podemos ver un ejemplo práctico de uso de nuestra clase Time en un bucle del videojuego con el siguiente código:

Time.init();
const jugador = {x: 0, velocidad: 200};
gameLoop();

// BUCLE PRINCIPAL
function gameLoop() {
    // Actualiza delta time al inicio del frame
    Time.update();

    // Aplica el delta time al movimiento
    jugador.x += jugador.velocidad * Time.deltaTime();

    // Resultado
    console.log(
      `Posición jugador: ${jugador.x.toFixed(2)} | Time.deltaTime(): ${Time.deltaTime().toFixed(4)}s`
    );

    // Siguiente frame
    requestAnimationFrame(gameLoop);
}

Este ejemplo de código realiza las siguiente acciones:

  • Time.init(); Registra el tiempo inicial del juego justo antes de arrancar para tener una referencia de salida.
  • const jugador = {x: 0, velocidad: 200}; Define la posición inicial del personaje (x: 0) y cuántos píxeles debe avanzar en un segundo completo (velocidad: 200).
  • gameLoop(); Ejecuta la función del bucle principal por primera vez para arrancar el ciclo infinito del juego.
  • function gameLoop() { Es el bucle principal del juego
    • Time.update(); Mide el tiempo transcurrido desde el frame anterior hasta el actual y guarda esa fracción de segundo en Time.delta_Time (por ejemplo, 0.0166 segundos a 60 FPS o 0.0041 a 240 FPS).
    • jugador.x += jugador.velocidad * Time.deltaTime(); Multiplica los 200 píxeles por la fracción de segundo actual (ej. (200 \times 0.0166 = 3.32) píxeles) y se los suma a la posición.
    • console.log(); Muestra los datos limpios en la consola. Al usar .toFixed(2), sólo se formatea el texto para que se pueda leer de forma cómoda, pero la variable física original (jugador.x) sigue manteniendo en secreto todos sus decimales intactos para no romper el movimiento fluido.
  • requestAnimationFrame(gameLoop); Le pide al navegador que vuelva a ejecutar gameLoop de forma infinita justo en el siguiente refresco de la pantalla.

Decimales y Delta Time

Si el juego corre a muchísimos FPS, el resultado de multiplicar por Time.deltaTime() puede ser menor que uno (ej. 0.83 píxeles), pero debemos dejar todos los decimales para que se vayan acumulando frame a frame. Si truncamos o redondeamos la variable jugador.x en esta línea, el 0.83 se convertirá en 0, se perderá el movimiento y el jugador se quedará completamente congelado en pantallas de alta tasa de refresco.

EL TRUCO: Para renderizar los personajes se puede usar una operación rapídísima que permite que el movimiento sea fluido y matemáticamente preciso en segundo plano, sin importar los FPS de la pantalla.

const xRender = jugador.x | 0; 

El operador | es una operación bit a bit de JavaScript y convierte el valor a un entero con signo de 32 bits antes de realizar la operación y no modifica la variable física original (jugador.x).

FPS vs Delta Time

Mover un juego en base a los FPS no es incorrecto en sí mismo; de hecho, es más sencillo y puede funcionar bien si los FPS son estables y controlados. Sin embargo, en entornos donde la tasa de FPS varía, esto afecta negativamente la experiencia de juego y puede generar problemas en la jugabilidad y en la sincronización de eventos. Por este motivo, es habitual utilizar el tiempo transcurrido para actualizar el movimiento y determinadas partes de la lógica, aunque los sistemas de física suelen utilizar técnicas adicionales como un timestep fijo.

A pesar de sus ventajas, el Delta Time en videojuegos no es una solución perfecta y tiene algunos inconvenientes. Uno de los principales problemas es que, si la tasa de FPS cae drásticamente (por ejemplo, de 60 a 10 FPS), el valor de Delta Time se vuelve muy grande, lo que puede provocar movimientos bruscos e inconsistencias en la física de los videojuegos, como colisiones imprecisas o saltos exagerados. Para mitigar este problema, muchos motores limitan el valor máximo del Delta Time. Además, los cálculos con Delta Time pueden introducir pequeños errores numéricos debido a la precisión de los cálculos en coma flotante, lo que a largo plazo podría generar ligeras desviaciones en posiciones y velocidades.

Conclusión sobre delta time en videojuegos

El Delta Time es una técnica que permite que los videojuegos funcionen de manera fluida y consistente, independientemente de las variaciones en la tasa de FPS. Sin él, los juegos pueden volverse más rápidos o más lentos según el rendimiento del hardware, lo que afecta a su jugabilidad.

Elegir entre usar Delta Time o basar el movimiento en un desplazamiento fijo por fotograma dependerá de los videojuegos que queremos desarrollar y de las consecuencias que puede tener una tasa de fotogramas variable.

Particularmente, yo utilizo un movimiento fijo por fotograma, pero tengo mis motivos. Principalmente, el hardware actual permite ejecutar juegos de tipo arcade a 60 FPS estables en prácticamente cualquier navegador. Mi problema suele ser precisamente el contrario: que los juegos pueden ejecutarse por encima de los 60 FPS dependiendo de la tarjeta gráfica y del monitor.

Para evitarlo, limito la frecuencia máxima a 60 FPS, por lo que puedo asegurar unas condiciones de ejecución bastante estables en mis juegos basados en ciclos. De esta forma, el movimiento fijo por fotograma resulta sencillo, predecible y, para el tipo de videojuegos que desarrollo, perfectamente válido.

Por supuesto, esto no significa que una técnica sea mejor que la otra. El Delta Time es una solución excelente cuando necesitamos que el juego sea independiente de la frecuencia de actualización, mientras que un movimiento fijo puede ser una alternativa perfectamente válida cuando controlamos las condiciones de ejecución.

Al final, como ocurre tantas veces en programación, no se trata de utilizar la técnica más sofisticada, sino la que mejor se adapta a las necesidades de nuestro videojuego.

¡ Espero que este artículo sea de vuestro interés !

Logotipo de Safe CreativeLogotipo de Creative Commons Attribution 4.0

Deja un comentario