Fortnite

Publicación técnica sobre el lanzamiento de Fortnite en Android

6.9.2018
Por El equipo de Fortnite

INTRODUCCIÓN

El 9 de agosto, lanzamos la beta de Fortnite en Android en dispositivos seleccionados de nuestros socios de Samsung. Pocos días después, comenzamos a enviar invitaciones a un subconjunto de dueños de dispositivos Android de entre una variedad de fabricantes de celulares. Hemos aprendido muchísimo de la beta en relación con el rendimiento, la seguridad, la compatibilidad de dispositivos y la distribución de Fortnite en Android a través del instalador de Fortnite. Sumerjámonos en los detalles técnicos que hay detrás del lanzamiento, en lo que estamos trabajando y dónde vemos Android en el futuro cercano.  

ESTADÍSTICAS

En los primeros 21 días del lanzamiento de Fortnite en Android, el interés ha sido extremadamente alto, más de 23 millones de jugadores entraron a la beta de Android y más de 15 millones de jugadores instalaron la APK.  Aunque nos encontramos en una fase de solo invitación para Android, la conversión de los jugadores que son invitados es similar a la de la beta de iOS. 
 

OPTIMIZACIÓN DE HARDWARE 


Introducción de la tecnología

Lanzar el mismo videojuego en todas las plataformas mientras se mantiene la compatibilidad para jugar en multiplataforma presentó un desafío único. Normalmente, cuando se trata de reducir un videojuego para dispositivos móviles, se simplifica el contenido e incluso el diseño para poder adaptarse a las restricciones de rendimiento de la plataforma. Por ejemplo, puede que se sacrifiquen objetos que están más cerca de la cámara para disminuir las llamadas de dibujo (draw calls). En Fortnite, los jugadores de Android pueden estar en la misma partida que sus amigos de PC y consola, por lo que tenemos que renderizar todo lo que afecte la jugabilidad.

El camino para el lanzamiento de Android

Desde enero de 2018, hemos estado trabajando duro con un gran equipo para entregarles la versión de Android de Batalla campal de Fortnite. Aunque la mayor parte de nuestro trabajo para hacer que esto fuera posible se centró en el rendimiento de renderizado, la estabilidad y la memoria, el mayor obstáculo que tuvimos que superar fue la cantidad y la variedad de hardware de Android, versiones de SO y versiones de controlador.

Trabajar con socios fue fundamental para llevar Fortnite a Android. Sin sus conocimientos, experiencia y trabajo duro, no hubiera sido posible.

Trabajamos estrechamente con Samsung para crear un perfil y optimizar Fortnite para sus dispositivos. Samsung envió ingenieros a varias oficinas de Epic alrededor del mundo y trabajaron directamente con nuestros ingenieros en optimizaciones y análisis de rendimiento, además de contribuir con muchos cambios de códigos, especialmente para el renderizador Vulkan. Al usar sus dispositivos de prueba y herramientas de ingeniería, pudieron indicarnos cuáles eran nuestros problemas en relación con el rendimiento y la memoria, además de cómo abordarlos. También trabajamos con Samsung para crear el proceso de instalación más fluido y más seguro que fuera posible para los usuarios de dispositivos Samsung.

Los ingenieros de Google también nos visitaron para crear un perfil y optimizar Fortnite. Nos ayudaron a identificar optimizaciones clave, una pérdida de memoria y también a ver cómo llevar a cabo una implementación de velocidad de fotogramas equilibrada para OpenGL en Android. Los ingenieros de Android en Google son muy talentosos y les apasiona hacer que el ecosistema de Android sea perfecto para jugar y que mejore constantemente.

Además, hemos podido trabajar con otros socios para probar y optimizar Fortnite, incluidos ARM, Qualcomm, Imagination Technologies, Razer, HiSilicon y muchos otros.
 

Fragmentación

El ecosistema de Android está formado por dispositivos creados por diferentes fabricantes. Cada dispositivo está diseñado en torno a un sistema en chip (SoC) que incluye una configuración de núcleos de CPU y GPU. Hay varias familias de SoC comunes, como Snapdragon de Qualcomm (con 71 % de los dispositivos compatibles actualmente), que tienen una GPU Adreno, Exymos de Samsung, la serie MT de MediaTek y la serie Kirin de HiSilicon, los cuales todos tienen una GPU Mali de ARM. Cada dispositivo ingresa al mercado con una versión ligeramente distinta del sistema operativo de Android y la mayoría de los fabricantes personalizan las características de gestión de energía y administración. Los dispositivos que tienen la misma GPU también ingresan con versiones de controlador gráfico distintas. El resultado es que dos dispositivos que comparten el mismo hardware pueden tener características de rendimiento muy diferentes y además están sujetos a errores distintos.

En realidad, nos sorprendió ver que la adopción de la última versión de Android es mucho más estable de lo que anticipamos para los dispositivos de 0 a 2 años de antigüedad. Actualmente en nuestra beta, con requisitos de dispositivo más altos, vemos que más del 92 % de los usuarios de Fornite están usando Android 8 (Oreo) o superior, cerca de 8 % usan Android 7 (Nougat) y menos del 0,5 % usan una versión de Android lanzada en el año 2015 o anterior. Para los dispositivos de 2 o más años de antigüedad, hay una disminución significativa. Para esos dispositivos, los fabricantes tienen que lanzar actualizaciones personalizadas y, en la mayoría de los casos, deben coordinarse con los distintos operadores de telefonía móvil que hay en todo el mundo para desarrollar y lanzar dichas actualizaciones.

Para abordar esta complejidad, utilizamos el sistema de perfil de dispositivos jerárquico en Unreal Engine. Primero, creamos cuatro perfiles de rendimiento: bajo, medio, alto y épico. Estos perfiles modifican los ajustes de adaptabilidad en el motor para permitir que el juego se ejecute en dispositivos con distintas características de rendimiento. El perfil bajo disminuye las distancias de visualización tan lejos como sea posible y deshabilita todas las características gráficas opcionales. El perfil épico tiene todo habilitado: las sombras, el follaje y la distancia de visualización más lejana que se pueda ejecutar en los dispositivos más recientes.

Además de esto, tenemos un conjunto de perfiles de GPU, como Adreno 54x y Mali G72. Estos perfiles de GPU eligen un perfil de rendimiento que se adapte mejor a las capacidades del hardware y nos permiten habilitar optimizaciones o métodos de solución alternativos necesarios para ese hardware en particular. Por último, tenemos un conjunto de perfiles específicos de dispositivo, como Adreno de Samsung Galaxy Note 9 y Google Pixel 2 XL. Esta última capa de perfiles de dispositivo nos permite habilitar más optimizaciones o métodos de solución alternativos en dispositivos específicos cuando es necesario. De arranque, observamos propiedades como el modelo del dispositivo, la versión del SO y la versión del controlador gráfico para determinar qué perfil de dispositivo se debe aplicar.
 

Rendimiento de renderización

El costo de renderización de la CPU fue, por mucho, nuestro mayor obstáculo de rendimiento para mantener una velocidad de fotogramas estable. Utilizamos mucho más tiempo de CPU en el controlador gráfico de Android en comparación con PC, consolas y iOS. Mientras que la mayoría de los dispositivos Android más recientes, como la versión de Adreno de Samsung Galaxy S9, pueden ejecutar más de 1500 llamadas de dibujo por fotograma, los dispositivos más antiguos pueden ejecutar muchas menos. Los dispositivos de gama media compatibles tienen que tener un promedio de 600 llamadas de dibujo aproximadamente y los de gama baja un promedio cercano a los 400.

Ya habíamos reducido la cantidad de objetos que necesitábamos renderizar en cada fotograma tanto como pudimos cuando lanzamos la versión de iOS a principios de este año, por lo que tuvimos que encontrar otras opciones. Experimentamos con llamadas de dibujo agrupadas dinámicamente en llamadas de dibujo instanciadas y esto proporcionó algunas ganancias, pero no fueron lo suficientemente significativas como para que valieran la complejidad del código agregado.

Algunas optimizaciones en el renderizador de OpenGL nos dieron algunas victorias, pero uno de los mayores triunfos fue una sorpresa y llegó como parte de una de nuestras optimizaciones de memoria: almacenamiento uniforme emulado. Esta es una ruta de código que UE4 admite hace años y se usa para dispositivos OpenGL ES2 que no tienen una compatibilidad nativa para almacenamientos uniformes, también llamados almacenamientos constantes. Así es cómo funciona. En el momento de la compilación de sombreadores, identificamos todas las constantes necesarias de un sombreador y las agrupamos en una matriz que puede leer el sombreador. Asimismo, guardamos una tabla de asignación que le dice al motor dónde reunir las constantes de los almacenamientos uniformes y en qué lugar colocarlas en la matriz constante. En el tiempo de ejecución, mantenemos almacenamientos uniformes en la memoria accesible de la CPU, usamos la tabla de asignación para copiarlos en un almacenamiento temporal y subimos todas las constantes con una sola llamada a función de glUniform4fv.

Aunque sigue siendo un misterio, la ruta de código del almacenamiento uniforme emulado nos ahorró una gran cantidad de tiempo en el controlador. Es posible que el controlador esté haciendo algo similar internamente y nuestra implementación sea más rápida para la carga de trabajo. También es posible que, como estamos creando y vinculando menos recursos, el controlador simplemente pasa menos tiempo administrando la vida útil de esos almacenamientos. Sea cual sea el caso, esta ruta disminuyó el costo del controlador entre un 10 % y 15 % en algunas circunstancias.
 

Vulkan

Vulkan es la API gráfica más reciente para Android y está diseñada para proporcionar un mejor rendimiento y acceso de bajo nivel al hardware. En el año 2016, colaboramos con Samsung para crear la demo ProtoStar y así demostrar lo que podía hacerse con una API gráfica de alto rendimiento en Android. Dado que Fortnite requiere que dibujemos muchos objetos en cada fotograma, Vulkan nos pareció la mejor opción. Desafortunadamente, no era una opción definitiva.

La compatibilidad de Vulkan aún no es un requisito en Android, por lo que no podíamos contar con que estuviera disponible en todo el ecosistema. Como nuestro objetivo son los dispositivos con hardware más reciente, no fue un problema muy serio para nosotros. Sin embargo, nos encontramos con varios errores y problemas de rendimiento en los controladores Vulkan antiguos. El resultado fue que OpenGL terminó siendo mucho más rápido y más estable que Vulkan en la mayoría de los dispositivos. Tampoco es una sorpresa: la industria ha tenido una década para optimizar y mejorar las implementaciones de OpenGL. Vulkan es una API más compleja y le llevará un poco más de tiempo alcanzar el mismo nivel de madurez.

Igual incorporamos la compatibilidad para Vulkan en Samsung Galaxy S9+ (Adreno) y Samsung Galaxy Note 9 (Adreno). Al trabajar en conjunto con los ingenieros de Samsung, logramos optimizar la compatibilidad de Vulkan de UE4 para que fuera un 20 % más rápido que OpenGL en promedio. En el futuro, seguiremos trabajando con nuestros socios de hardware para otorgarles una compatibilidad de Vulkan de alto rendimiento en otros dispositivos y así darles una mejor experiencia a los jugadores de Fortnite en Android y mejorar el rendimiento de los controladores Vulkan para todos los desarrolladores.
 

Memoria

La memoria es una lucha constante. No solo porque lanzamos un videojuego de consola en un dispositivo móvil, sino porque estamos continuamente agregando contenido nuevo. Por eso, siempre estamos buscando desarrollar optimizaciones de memoria. Android presenta desafíos únicos en comparación con otras plataformas.

No existe un presupuesto de memoria que podamos tener como objetivo. Cada dispositivo tiene una cantidad de memoria distinta, diferentes tipos de aplicaciones ejecutándose en segundo plano y, potencialmente, diferentes políticas para tomar la decisión de eliminar una aplicación por usar demasiada memoria. No hay ninguna API para consultar cuál es el presupuesto de memoria. Durante una prueba de memoria, ingresamos a una partida y comenzamos a asignar memoria hasta que el SO acabó con el proceso. Al usar teléfonos reiniciados sin iniciar ninguna otra aplicación, en un Samsung Galaxy S8 (Mali) logramos asignar 3 GB de sus 4 GB de memoria total antes de que finalizara el proceso. En un Google Pixel 2, solo pudimos asignar 1,8 GB de sus 3,6 GB de memoria total.

El sistema, especialmente el controlador gráfico, asigna mucha memoria por nuestra parte. UE4 rastrea toda la memoria que solicitamos del SO directamente, incluso una estimación de asignaciones de memoria de la GPU, pero no podemos ver bien qué asigna el controlador. A través de experimentos, descubrimos que la mayor parte de la memoria que el controlador estaba asignando en Fortnite se reducía a sombreadores.

La razón por la que creamos la optimización de almacenamiento uniforme emulado que mencionamos antes fue por la memoria. OpenGL requiere que la aplicación pueda consultar la ubicación de cualquier miembro de un almacenamiento uniforme. Por ejemplo, se puede solicitar a OpenGL el desplazamiento de LocalToWorldMatrix dentro del almacenamiento uniforme primitivo. Para poder respaldar esto, el controlador tiene que mantener metadatos en la memoria, como una tabla de desplazamiento, que incluya cadenas con el nombre de cada miembro y tiene que hacerlo para cada programa.

En Fortnite, tenemos una gran variedad de sombreadores. Durante una sesión de juego normal, el motor usará alrededor de 2000 programas de sombreador diferentes. Dentro de cada uno de estos programas de sombreador, el controlador parece almacenar estos metadatos, lo cual agrega mucha memoria. ¡Ahorramos más de 400 MB de memoria en Fortnite al usar los almacenamientos uniformes emulados!

Cuando lanzamos Fortnite en Android por primera vez, nuestras pruebas internas indicaron que estábamos dentro de las restricciones de memoria de los dispositivos objetivos. Realizamos pruebas en las que activamos el GPS en Google Maps, pusimos música y nos aseguramos de que podíamos jugar Fortnite sin ningún problema. No obstante, cuando lanzamos el juego, descubrimos que muchos jugadores tenían problemas de bajo rendimiento o que el juego se cerraba inesperadamente debido a falta de memoria.

Cuando un dispositivo Android se está quedando sin memoria, trata de liberar recursos al cerrar aplicaciones que no están en uso. Sin embargo, resulta que hay ciertas aplicaciones y servicios que se ejecutan en segundo plano ahí afuera que simplemente se reinician cuando el SO las cierra. ¡Esto empeoró la situación! Android cierra la aplicación para recuperar memoria, pero esta se reinicia y empieza a consumir tanta memoria como antes. Iniciar y detener aplicaciones consume tiempo de CPU, por lo que no solo no logramos liberar espacio, sino que estamos usando muchos recursos de CPU innecesarios, lo que es peor.

Actualizamos nuestros procesos de prueba para instalar y ejecutar más aplicaciones comunes que la mayoría de los usuarios usan para poder encontrar estos problemas antes, pero aun así necesitábamos disminuir el uso de memoria, y rápido. Pudimos reducir el problema para los usuarios que ejecutan ajustes altos y épicos en dispositivos Snapdragon de Qualcomm con 4 GB de memoria. Nuevamente, la memoria de sombreador parecía ser la diferencia principal. Como medida provisional, deshabilitamos las sombras y esto ayudó a aliviar el problema. Al hacerlo, disminuimos la cantidad de sombreadores requeridos debido a que ya no necesitábamos las variantes para buscar y filtrar los mapas de sombras. También añadimos una memoria caché de LRU para los sombreadores. La memoria caché nos permite conservar solo los programas de sombreadores necesarios para renderizar la escena actual en la memoria. Otros programas de sombreadores se guardaron de forma comprimida en la memoria. Cuando sea necesario, los descomprimiremos y los devolveremos al controlador.
 

Futuro: próximos pasos

Ahora mismo, nos estamos concentrando en hacer que el juego se ejecute bien en todos los dispositivos compatibles actualmente y en recuperar suficiente memoria para poder mejorar la estabilidad y la calidad visual. Luego, observaremos problemas de compatibilidad como el sonido. En el lanzamiento de la v.5.40 corregimos algunos problemas de sonido en varios dispositivos e hicimos que más dispositivos fueran compatibles. Además, planeamos darles a los usuarios un control más detallado para personalizar sus dispositivos y realizar intercambios entre calidad y rendimiento.

Seguiremos mejorando la compatibilidad de Vulkan y la incorporaremos en más dispositivos con el tiempo. Esto significa seguir trabajando con los fabricantes de dispositivos para desarrollar optimizaciones, tanto en UE4 como en sus controladores. A largo plazo, invertir tiempo en mejorar la compatibilidad de Vulkan y los controladores nos ayudará a proporcionar un mejor rendimiento para los jugadores y en todos los videojuegos de UE4 lanzados en Android.

Seguiremos investigando los dispositivos más antiguos y más lentos, pero es poco práctico ir más atrás. Cada año, los celulares de última generación se están volviendo un 50 % más rápidos que el año anterior. Fortnite se ejecuta adecuadamente en dispositivos de dos años de antigüedad, bien en dispositivos de un año de antigüedad y muy bien en dispositivos que fueron lanzados este año. ¡A este paso, solo imagínense cómo se verá Fortnite en los dispositivos que se lanzarán el próximo año!

image2.png


Por último, muchas de las optimizaciones de código que realizamos en Unreal Engine ya se incorporaron con el lanzamiento de UE4 4.20. Las optimizaciones que faltan se incorporarán en el próximo lanzamiento 4.21, y seguiremos compartiendo las optimizaciones futuras con todos los desarrolladores de UE4.
 

LA BATALLA CONTRA LOS MALWARES   

Incluso antes de que anunciáramos que Fortnite estaría disponible en Android, nos dimos cuenta de que aparecieron sitios web de "Fortnite en Android" que no estaban autorizados. Normalmente, son servidores de malware o estafas.  A medida que encontramos estos sitios, buscamos eliminarlos con los mismos sitios web, los proveedores de servidor relevantes y cualquier anuncio o video que los promueva.  Aunque puede que esos sitios web estén o no distribuyendo malwares, consideramos que todas las distribuciones y las presuntas distribuciones de Fortnite en Android no están autorizadas. La única fuente legítima para conseguir Fortnite en Android es directamente a través de Epic por medio del instalador de Fortnite oficial.
 
Hasta el momento, Epic ha tomado acciones contra 47 sitios web de "Fortnite en Android" no autorizados, muchos de los cuales parecían estar operados por los mismos actores de mala fe. Seguimos controlando la situación con el objetivo de eliminarlos o restringir el acceso al aprovechar la conexión de Epic a una red de socios antifraudes (incluye proveedores de servicio de Internet, compañías de navegadores y compañías de antivirus) que pueden implementar una alerta en el navegador como la siguiente: 

Image1.png
 
Buscamos activamente nuevos sitios web de malware a medida que aparecen con un equipo interno que está dedicado a esta tarea. Además, contratamos a una agencia de control antifraudes e IP de terceros para expandir nuestros esfuerzos de vigilancia. Esta asociación nos permite detectar y monitorear nuevos dominios que se registran con URL sospechosas para que, si evolucionan en sitios web maliciosos, Epic pueda tomar las acciones apropiadas, que pueden incluir demandas.

CONCLUSIÓN

Fortnite en Android representa muchas primeras veces para la industria. La primera vez que un videojuego de PC y consola se lanza en Android con la opción de jugar en multiplataforma y compatibilidad total, además de ser el primer videojuego exitoso que se lanza fuera de Google Play Store. Fue un proceso de aprendizaje y dedicación enorme, pero la rápida adopción de más de 15 millones de usuarios de Android demuestra que este enfoque es bueno y puede ser muy exitoso. Y, lo más importante, es que todo el trabajo técnico que hemos realizado para Fortnite en Android estará disponible para todos los desarrolladores de Unreal Engine con la versión 4.21, así todos pueden beneficiarse de este trabajo.