DeltaTime Tutorial

en Tutoriales, UE4

¿Por qué necesitamos utilizar Delta Time?

Seguro que has visto alguna vez un viejo juego funcionando en un dispositivo de gama alta como si alguien hubiera apretado el botón de avance rápido, o el caso contrario, un juego con unos requisitos elevados intentando funcionar el un viejo dispositivo con un resultado desesperante. Para solucionar este problema tenemos que hacer nuestro juego  framerate independiente, y para conseguirlo debemos aplicar el Delta Time.

Delta time (Δt) es el tiempo transcurrido desde el último frame, o usando otras palabras, es el tiempo entre cada frame renderizado.

Un juego tiene, basicamente, el siguiente diagrama de flujo. El juego comienza inicializando algunos datos y entra en un bucle de actualización, dentro de este bucle se procesa la entrada de usuario, se actualizan los datos del juego y se dibuja la nueva escena. Cuando el juego termina el programa finaliza.

gameflow

Vamos a imaginar que estamos creando nuestro propio motor, necesitamos programar nuestro bucle de actualización, la primera aproximación es hacer un bucle while y dentro de este pondremos las llamadas al procesamiento de los datos ( entrada de usuario, colisiones, etc.) y el dibujado de la escena. En realidad no necesitamos actualizar la escena con cada tick de CPU por muchos factores, por ejemplo, el monitor tiene una tasa de refresco limitada, normalmente de 60hz (solo puede mostrar 60 frames por segundo), o, el ser humano medio sólo puede percibir cerca de 150 fps, por estas razones no necesitamos dibujar 2000 frames por segundo.

Supongamos que queremos dibujar 5 frames por segundo, por lo tanto vamos a poner un sleep de 0.25 segundos antes del final de la iteracion del bucle. 1 segundo / 4 huecos = 0.25 segundos por hueco.

Game()
{
	InitializeGame();
	while(!EndGame())
	{
		UpdateData();
		Draw();
		Sleep(0.25);
	};
};

Podemos decir que nuestro Delta Time es de 0.25 segundos.

deltatime_5fps

Con un valor de fps mas bajo el Delta time se incrementa. Como se puede ver en la siguiente imagen, con un valor de 3 FPS el delta time se incrementaría hasta 0.5 segundos. 1 segundo / 2 huecos = 0.5 segundos por hueco

deltatime_3fps

Ahora que ya sabemos que es el delta time vamos a explicar como puede utilizarse.

Supongamos que queremos mover un cuadrado por la pantalla. Vamos a aplicarle un movimiento uniforme por lo que podemos expresar su desplazamiento con la siguiente fórmula:

Δs = V * Δt

donde s = desplazamiento, V = velocidad, t = tiempo. La posición actual del cuadrado en cada frame es la suma de los Δs que se han ido calculando en los frames previos más el Δs del frame actual.

Por lo tanto es obvio que necesitamos aplicar Δt del frame actual para conocer exactamente las posición del cuadrado

Ahora podemos hablar del nodo Event Tick de UE4. Este evento es llamado con cada frame y tiene un parámetro que nos da el time real que ha transcurrido desde el tick anterior, este es nuestro Delta time.

En las anteriores lineas hemos estado asumiendo que el valor de delta time era el mismo entre cada frame, pero la realidad es que su valor es variable, dependiendo de factores como la carga del dispositivo se puede ver afectado, y el contador de FPS en realidad es un valor medio de cada segundo.

deltatime_variablefps

Por lo tanto necesitamos conocer el valor delta del frame actual y también los distintos valores de los frames anteriores, no nos sirve con almacenar el valor del primer frame y utilizarlo para todos los frames.

Vamos a construir un ejemplo sin usar Delta time. Vamos a añadir un pixel a la coordenada X de nuestro cuadrado en cada llamada a Tick event. Con una tasa de refresco de 100 FPS obtendremos un desplazamiento de 400 pixels en 4 segundos.

Tick Event with no delta time

¿Pero qué pasa si la tasa de fps desciende?. Nuestro cuadrado necesita más tiempo para cubrir la misma distancia!. Con un valor de 70 fps necesitamos aproximadamente 5.71 segundos en vez de los 4 segundos iniciales. 400 píxeles / 70 píxeles por segundo = ~5.71 segundos. Con 40 FPS el tiempo se incrementaría hasta los 10 segundos!

Ahora qué ocurre si introducimos el valor de delta time en nuestra función. Usando la fórmula anterior donde V = 100 píxeles por segundo.

Tick Event with Delta Time

Ya no hay prácticamente diferencias en el tiempo necesario para cubrir la misma distancia. Estamos calculando el desplazamiento variable de cada frame correctamente para que corresponda con la velocidad deseada.

Con valores de FPS menores el Delta Time se incrementa, los desplazamientos en estos frames son mayores pero tenemos menos frames, por lo tanto en el resultado de la suma final es el mismo. Ahora podemos decir que el juego es framerate independente.

UE4 annexo

Durante la explicación del delta time hablamos de que no necesitábamos actualizar la escena con cada tick de CPU, es un desperdicio de recursos. Una manera de reducir las llamadas al Tick Event para un Actor es establecer un intervalo mayor en la sección de detalles.

Podemos configurar varias opciones de Tick, entre las que se incluye la frecuencia de llamada.

Ayudanos con este blog!

El último año he estado dedicando cada vez más tiempo a la creación de tutoriales, en su mayoria sobre desarrollo de videojuegos. Si crees que estos posts te han ayudado de alguna manera o incluso inspirado, por favor considera ayudarnos a mantener este blog con alguna de estas opciones. Gracias por hacerlo posible!

Escribe un comentario

Comentario