Arreglando los bugs más comunes de los AAA

Feb 22

Arreglando los bugs más comunes de los AAA

Atención: Me encantan estos juegos, Far Cry 3, 4, GTA V, los tengo para consola y me lo paso pipa jugando con ellos, aclarado esto, empezamos.

Este post va sobre cómo se podrían arreglar los bugs de FarCry 3 que considero más relevantes y que parece que vienen arrastrando desde anteriores versiones y de los cuales, algunos siguen estando en las siguientes (FarCry 4).


 

Bugs en la versión de PS3, después de aplicar todos los parches hasta la última versión -Febrero 2015-:

Veámoslos uno a uno:
1- Rendering:

* error en el dibujado de las sombras dinámicas

Diferencia entre sombras FC3 - PS3 vs XBOX 360

Diferencia entre sombras FC3 – PS3 vs XBOX 360

-explicación:

Las sombras estáticas se queman con el proceso conocido como baking en una escena pero lo que ocurre a menudo con el engine de Far Cry 3 (UDK) es que si te acercas a alguna pared o si te agachas y miras al suelo enfocando una sombra, esta parpadea o tiene un patrón de agujeros, la resolución usada no es lo que más se nota al cambiar sino la calidad de la sombra proyectada cuando está demasiado sucia. Podemos ver fallos de dibujado de sombras en casi todo el juego, sobre todo para objetos con texturas transparentes y de tamaño medio que proyectan y reciben sombras.

– solución:

Para arreglarlo puede que no sea trivial pues al cambiar la distancia de la sombra el rendimiento podría empeorar y bajar de 30FPS así que se suele cambiar la calidad y los objetos que proyectan sombra para que no lo hagan. La solución posiblemente sería cambiar los shaders que proyectan y pintan las sombras de los objetos sobre las texturas de los materiales, estudiando cuál sería el mejor para cada plataforma, podemos ver que las sombras son distintas en PS3 y en XBOX 360.

* bug en objetos con pelo “complejo”:

– explicación

Las cabezas con pelos en Far Cry 3 a veces dan fallos de renderizado, no se pintan bien cuando hay muchos pelos juntos, es decir, aparecen parches blancos, o simplemente el pelo desaparece.

hair_glitch_FC3

– solución

El problema se soluciona corrigiendo el orden o índice Z de cada material, a veces es simplemente que los pelos están mal colocados, otras que el orden Z no es el correcto por lo que se pinta antes que el fondo (cielo,nubes,árboles) por lo que al pintarse antes de tiempo el rendering del pelo está debajo de donde debería estar.

* glitches de texturas estiradas

textura_estirada_farcry3

estos fallos son más bien del propio diseñador del nivel por lo que no hace falta comentarlos, sólo que si se ven mucho en terrenos, el bug sería del generador de los mapas UV del terreno.

* bug con el cambio del nivel de detalle de objetos  (LOD)

– vídeo

– explicación

Para ahorrar recursos cuando tenemos una cámara que renderiza con un FOV de 60+ y unos límites del plano de proyección en perspectiva con near 0.1 y far 1000 o más, las cosas se complican, necesitamos usar la técnica del nivel de detalle, con esto, dibujamos una versión reducida en detalles, polígonos y texturas de los modelos cuando están lejos y el de mayor calidad cuando están cerca.

Esto en realidad no es un bug, sino algo mal elegido, que es el umbral donde se cambia el LOD (o nivel de detalle) bueno al malo demasiado pronto, es decir, el umbral es muy pequeño o muy lejano, es posible que el motor no soporte muchos objetos con nivel de detalle alto por lo que se han visto obligados a hacerlo.

– solución

Si el hardware no permite usar LOD de un nivel bueno, intentaríamos usar un modelo que entre en el batching estático, así, podemos tener modelos muy sencillos pero que se agrupan todos en una llamada de dibujo, el problema es cuando tienes muuchos tipos de modelos (árboles distintos, edificios, plantas,etc), en ese caso se optaría quizás por no dibujarlos y hacer un fade en función de la distancia, en lugar de que aparezcan directamente que es MUY CANTOSO. XD

Aquí tenéis una solución que dieron en Far Cry 3, usar directamente una resolución súper baja para texturas en objetos que son difíciles de encontrar (estaba en un poblado en una tienda).

lod0-3

2.- Memoria

* bug de memoria al realizar transiciones

– explicación

cuando se cambia de nivel se hace una transición, aquí se ha de liberar memoria, se suele utilizar un recolector de memoria para ello, pero si haces operaciones con la memoria sin tener en cuenta los estados de las transiciones entre escenas e interfaz pueden aparecer fallos de memoria en pantalla.

Aquí un error de transición entre estados de una misión:

3.- Inteligencia Artificial

son los bugs más importantes en los AAA, pero a la gente les parecen graciosos!, y no es para menos. Curiosamente cuando un juego funciona perfectamente bien, como ocurre con el nuevo The Order 1886, la gente se aburre, por eso vemos tantos bugs de los que parece que las compañías no se preocupan tanto, porque sino el juego parecería demasiado un producto y no algo destinado a la diversión, con sus fallos, quizás ,me he planteado, que estos bugs estén puestos a drede o que al encontrarlos ,no los hayan querido eliminar porque el propio equipo se divertía con ellos y sólo ocurren en un determinado número de casos.

* bug en el cambio de estado de la máquina de estados

– explicación

en complejos sistemas de I.A. como los que predominan en los AAA se usan una serie de cómodas máquinas de estados, estas permiten a un personaje, NPC, o cualquier otro objeto del juego que necesite una mínima IA , pasar de un estado a otro.

En FarCry podemos tener una máquina de estados para un enemigo, que empiece por defecto estando en reposo, de forma que gasta la menor cantidad posible de recursos, si está muy lejos de la cámara ni siquiera estará activado -esto se puede hacer por zonas o sectores o simplemente por distancia, lo vemos en la sección de LOD-,  y al ser activado se hará a través de un evento activador, también llamado “trigger”, este evento en forma de función se puede llamar desde otro objeto, desde el código principal del juego, a través de la red, o como resultado de una cadena de eventos, o por una activación en masa, se me ocurren multitud de otros casos posibles, pero con esos es suficiente.

Al llegar el evento, se analiza y se establecen las condiciones para cambiar del estado actual al que el evento sugiere, a veces puede ser un cambio directo (si toca el agua estás nadando) y otras es una consecuencia de los cambios que genera el evento (al recibir un impacto de bala restas vida, si queda 0 pasar a estado muerto ,sino, herido), este nuevo estado ejecutará una transición de animaciones, cambios en la interfaz de usuario, y pasa a la exploración del árbol de su comportamiento para cada frame por otro nodo.

Si el soldado estaba en estado de espera y se activa por un evento por proximidad, pasa al estado patrullando, esperando a que sus sensores de visibilidad detecten enemigos, en ese momento pasaría al estado de ataque, que puede contener subestados como ataque-cobertura-protegerse-esquivar, y así seguirá hasta que las condiciones del bucle para su comportamiento asociado hagan que cambie de estado a otro, por ejemplo, herido->vuelta al ataque, muerto->cadáver->eliminar de memoria, o vuelta a descanso (idle) para ahorrar recursos del dispositivo.

– solución

está claro que en los vídeos, hay una condición que ha hecho que el estado de la IA pase a muerto, pero por qué se encuentra el personaje parado y con una animación y sonidos descoordinados de su estado? porque el evento que ha llegado después del evento de morir  ha sobreescrito las variables y con ellas las animaciones, no se ha tenido en cuenta una condición por lo que se ha pasado a la animación del estado vivo pero está ya muerto, aquí hay en realidad dos bugs, no comprobar cuál es el orden de llegada de eventos  y no comprobar que estemos pasando a un evento incorrecto. Solución: aplicar parche al código para comprobar que los eventos que llegan son correctos desde el evento en el que estamos, es decir, si el personaje tiene 0 de vida, no puede pasar a un estado vivo.

 

* bug en el trazado de la ruta óptima, algoritmo A* para geometría 3D

– vídeo con el mismo error en Far Cry 4 con un tigre y GTA5 con vacas

– explicación

para llegar a una posición una entidad del juego con IA usa su motor de movimiento propio al que le pide moverse hacia un objetivo. Qué ocurre si para llegar a un punto, el motor de movimiento nos lleva por los cerros en lugar de ir directamente?, una de dos, o es un problema de coordenadas de la ruta de navegación o un error del motor que no encuentra una manera de usar las rutas del mapa de nodos.

– solución: 2

S1: añadir nodos en las rutas e,intentar cambiar la estrategia si el número de nodos que devuelve el algoritmo A* es mucho mayor que la distancia que recorrería un patrón de movimiento sencillo con físicas como steering behaviour modificado.

S2: A veces sólo hay que cambiar un pequeño parámetro en el trazado de rayos para encontrar colisiones del nodo actual al siguiente, quizás la geometría de la malla de colisión con la que choca el rayo de navegación es demasiado compleja o demasiado simple y bastaría con cambiarla.

* bug

4.- Programación, física y geometría del juego

* bug que hace que atravieses la geometría del nivel

– En el primer vídeo de este post hay un enemigo disparando al jugador desde dentro de una roca

– explicación

Me extraña que las balas no choquen con la roca interior, pero este bug está muy relacionado con el último de la anterior sección. El trazado de rayos es como tener unos ojos virtuales en una IA, que nos permiten conocer qué geometría hay a nuestro alrededor.

El problema de las físicas en un mundo con una geometría tan compleja puede explicarse fácilmente porque las mallas de colisión para la geometría del terreno no suele ser hecha a medida sino que es la misma que la del terreno en sí, y a veces se generan mallas de colisión encapsuladas unas dentro de otras, en el caso de una cueva bajo una montaña es claro, hay una pequeña cavidad de roca por encima de un nivel de geometría de terreno. Por debajo del terreno ,por debajo de la roca, hay una cueva, debajo de la cueva, agua y más terreno. Suena complejo verdad?, pues así ocurre lo que ocurre, cuando entras dentro de la cueva y llevas una velocidad suficiente (usando un vehículo) como para que al colisionar con la pared de la cueva, el vehículo se rompa, el personaje saldrá despedido y en ese evento, el punto de referencia se toma usando un rayo, aquí es donde está el bug, es muy dificil determinar qué coordenadas tomar como origen del rayo y qué vector elegir para dirigir el rayo de colisión para colocar al personaje ahí en el primer punto donde colisione. El bug consiste en que el rayo se lanza dentro del espacio entre el techo de la cueva, que tiene ,si recordáis, una roca encima, por lo que estás metiendo al personaje en el primer punto de colisión desde el techo de la cueva (el suelo de la roca), hacia el cielo, pero dentro de la roca, evidentemente, el rayo no sale de la roca pues la geometría de la propia roca es con la que choca el rayo y así, dejas encerrado al jugador en una jaula del modelo de la roca y el suelo por encima de la cueva.

– solución

este es uno de los retos más complicados que he encontrado a la hora encontrar bugs en el juego e intentar solventarlos, debido a lo grande que es la geometría y de lo diferente que puede llegar a ser, una posible solución sería usar la propia posición del vehículo y no usar un rayo sino una fuerza explosiva que lo lance en la dirección opuesta, ya que si intentas encontrar un punto desde arriba sería imposible en el caso de que hubiera una montaña ya que estás dentro de una cueva y la distancia es mucho mayor que el límite máximo permitido para soltar al jugador al explotar el vehículo. Si lanzas el rayo desde abajo ocurre lo mismo, por lo que el trazado de rayos tiende a devolver un error y a no ser factible.

Como véis se trata de un problema de usar la propia posición del vehículo y encontrar una zona segura donde soltar al jugador, y es que puedes generar una interferencia entre el colisionador del vehículo y el del jugador para empezar, por lo que el rayo aquí debería servir para encontrar una posición segura donde no exista ningún colisionador cercano pero no sirve debido a que la geometría alrededor es sumamente difícil de visualizar matemáticamente.

Una solución posible sería usar un nodo cercano  que devuelva del algoritmo A* con nodos de terreno, pero al ser la geometría tan compleja con diferentes alturas y el vehículo puede estar entre varias rutas, cuál sería el criterio para elegir el nodo?: un lugar en la misma altura que no tenga colisionadores alrededor, para eso hay que saber qué radio elegir para la detección, lo cual en sí es otro problema añadido.

Otra solución, hacer una búsqueda cuadrada en espiral

con una esfera del radio del colisionador del jugador y encontrar un hueco desde el punto del vehículo -como en juegos de dos dimensiones-, si no hay nada vacío en esa búsqueda digamos de 10 iteraciones sencillas que consumen poco, entonces buscar un nodo de spawn o reinicialización próximo y seguro, por ejemplo, encontrar a una distancia del radio entre las últimas posiciones de la trayectoria guardada del vehículo.

Si esta última solución no te gusta, puedes crear un colisionador esférico que se mueva en la zona del vehículo (no colisiona sólo es un trigger) usando una fuerza de explosión, lo que haya hasta la posición de terreno más cercana hacia el suelo desde el vehículo, comprobando si hay otros colisionadores dentro ,con un radio adecuado y comprobando el suelo y el techo, aunque esto podría generar más iteraciones y finalmente el peor caso ya que podría no tener solución y computacionalmente es muy costoso.

Solución mixta: usar una mezcla de las anteriores, tomando la posición del vehículo, obtener el punto A* de terreno + altura del radio del jugador, el más cercano sin colisiones alrededor y colocar allí una esfera, desactivar temporalmente el colisionador del jugador y animar la explosión con matemáticas simulando -es básicamente una parábola- que vuela hasta el punto destino, donde la esfera colisionadora tiene reservado nuestro sitio, entonces borrarla y reactivar los colisionadores del jugador.

Conclusiones:

1) es el terreno generado? se podrían colocar los puntos de aparición a mano

2) son los demás personajes prioritarios? vehículos, otros jugadores, npc’s esto nos ahorraría muchos cálculos

3) sería factible usar un colisionador que crezca de forma que aparte el espacio desde la coordenada inicial con tamaño 0 hasta el radio del colisionador del jugador (siempre con la velocidad por debajo del límite de frames de ejecución del motor físico para que de tiempo a manejar las colisiones con todos los objetos)?

* bug que coloca los objetos volando

fc3_terrain_bug

y el bug que hace que un objeto se coloque por debajo de la geometría

– vídeo

– explicación

En el vídeo vemos en el minuto 1.10 como un NPC atraviesa el coche, esto pasa cuando el ritmo al que se procesa el mundo físico va descompasado (más rápido o más lento) que el mundo de los objetos, si no le da tiempo a detectar la primera de las colisiones o incluso si lo detecta pero luego se equivoca, son dos casos distintos.

Otro bug, basado en el bug anterior pero aplicado para npc’s y otros objetos del juego que no son el jugador, ocurre por los mismos problemas, con el añadido de que al ocurrir en cada frame, no puede tener un alto coste de computación, un tigre subiendo las escaleras que te ataca ,al saltar la animación e intentar devolverlo a una posición correcta de geometría ,el rayo se traza mal y se puede poner por debajo de unas escaleras cuando estaba por encima al atacarte.

 

– solución

la misma que la anterior pero reduciendo las iteraciones y comprobaciones a uno, añadir que el punto encontrado no puede estar a una distancia límite en altura de más de 2m porque entonces se encuentra a otro nivel de geometría, es decir, por encima o debajo del suelo donde se encontraba antes ,o al menos en visión del jugador,…en cualquier caso acaba de atacar al jugador, no puede estar demasiado lejos de este!.

Para el caso del coche que choca con el NPC, lo importante para solucionarlo es llegar a la mejor medida de frames del mundo físico para que vaya acompasado al del mundo de los objetos (entidades gameObject).

* bug de programación en las habilidades

bug_habilidades_farcry3

–  explicación

me pasó que al tener puntos para desbloquear las habilidades, no me permitía desbloquearlas poniéndome de motivo que no había adquirido otra previa en el árbol, aunque sí que la tenía por lo que se quedó bloqueado el resto del árbol, como véis, tengo 3 puntos disponibles pero no puedo desbloquear las últimas habilidades que quedaban, esto ocurrió porque en una de las partidas se guardaron los puntos disponibles y habilidades adquiridas pero o bien en otra partida se sobreescribió o bien las sumas no coinciden por un error de lectura/escritura.

– solución

comprobar las sumas de puntos disponibles-gastados = habilidades adquiridas, desbloquear o bloquear nodos del árbol en función de eso, para que concuerden al cargar el juego.

5.- Conexión a Internet

* bug en multiplayer que hace que aparezcas muerto

– explicación

al no sincronizar bien con algoritmos de carga balanceada los estados de cada jugador online, se puede dar mucha ventaja a los que tengan la mejor conexión (mejor ping) por lo que los jugadores que tienen lag morirán antes, es un fallo bastante conocido que ha llevado a una nueva forma de pelear online bautizada como “lag warriors”.

– solución

añadir algoritmos predictivos y carga balanceada a las acciones de los jugadores online.

* bug en la conexión con PSN a través de la web

– explicación

Al intentar conectarte con la app o la  web a la red de PSN da un error aunque el login esté ok, seguramente habrán cambiado la API ,recuerdo que incluso un juego de Sony en móviles daba errores con dicha API de PSN.

– solución

actualizar el SDK de integración con PSN ,try again.

 

Y eso es todo,espero que os haya gustado.

English version of this post, featured in Gamasutra.

 

Artículos relacionados

  • ...

Exprésate dejando un comentario:

Introduce el captcha

Por favor escriba los caracteres de la imagen captcha en el cuadro de entrada